Exemplo n.º 1
0
    async def __call__(self):
        tm = get_tm()
        await tm.abort()
        ws = web.WebSocketResponse()
        await ws.prepare(self.request)

        async for msg in ws:
            if msg.type == aiohttp.WSMsgType.text:
                try:
                    message = ujson.loads(msg.data)
                except ValueError:
                    logger.warning(
                        'Invalid websocket payload, ignored: {}'.format(
                            msg.data))
                    continue
                if message['op'] == 'close':
                    await ws.close()
                elif message['op'].lower() == 'get':
                    txn = await tm.begin()
                    try:
                        await self.handle_ws_request(ws, message)
                    except Exception:
                        logger.error('Exception on ws', exc_info=True)
                    finally:
                        # only currently support GET requests which are *never*
                        # supposed to be commits
                        await tm.abort(txn=txn)
            elif msg.type == aiohttp.WSMsgType.error:
                logger.debug(
                    'ws connection closed with exception {0:s}'.format(
                        ws.exception()))

        logger.debug('websocket connection closed')

        return {}
Exemplo n.º 2
0
    def __run(self, app, settings):
        if asyncio.iscoroutinefunction(self.run):
            # Blocking call which returns when finished
            loop = asyncio.get_event_loop()
            loop.run_until_complete(self.run(self.arguments, settings, app))
            try:
                loop.run_until_complete(self.cleanup(app))
                loop.close()
            except (asyncio.CancelledError, RuntimeError):
                logger.warning('Cancelled error on cleanup')
        else:
            self.run(self.arguments, settings, app)

        if self.profiler is not None:
            if self.arguments.profile_output:
                self.profiler.dump_stats(self.arguments.profile_output)
            else:
                # dump to screen
                self.profiler.print_stats(-1)
        if self.line_profiler is not None:
            self.line_profiler.disable_by_count()
            if self.arguments.line_profiler_output:
                self.line_profiler.dump_stats(
                    self.arguments.line_profiler_output)
            else:
                self.line_profiler.print_stats()
Exemplo n.º 3
0
    async def __call__(self):
        tm = get_tm()
        await tm.abort()
        ws = self.request.get_ws()
        await ws.prepare()

        async for msg in ws:
            try:
                message = msg.json
            except WebSocketJsonDecodeError:
                # We only care about json messages
                logger.warning(
                    "Invalid websocket payload, ignored: {}".format(msg))
                continue

            if message["op"].lower() == "close":
                break
            elif message["op"].lower() == "get":
                txn = await tm.begin()
                try:
                    await self.handle_ws_request(ws, message)
                except Exception:
                    logger.error("Exception on ws", exc_info=True)
                finally:
                    # only currently support GET requests which are *never*
                    # supposed to be commits
                    await tm.abort(txn=txn)

        logger.debug("websocket connection closed")
        await ws.close()
Exemplo n.º 4
0
def get_settings(configuration):
    if configuration == 'config.yaml' and not os.path.exists(configuration):
        # try config.json as well...
        configuration = 'config.json'
    if os.path.exists(configuration):
        with open(configuration, 'r') as config:
            if configuration.lower().endswith('.json'):
                settings = json.load(config)
            else:
                # should be yaml then...
                settings = yaml.load(config)
        settings['__file__'] = configuration
    else:
        try:
            settings = json.loads(configuration)
        except json.decoder.JSONDecodeError:
            # try with yaml parser too..
            try:
                settings = yaml.load(configuration)
            except yaml.parser.ParserError:
                settings = None

    if settings is None or settings == configuration:
        if 'logged' not in MISSING_SETTINGS:
            logger.warning(f'Could not find the configuration file '
                           f'{configuration}. Using default settings.')
        MISSING_SETTINGS['logged'] = True
        settings = MISSING_SETTINGS.copy()
    return settings
Exemplo n.º 5
0
    async def __call__(self):
        tm = get_tm(self.request)
        await tm.abort(self.request)
        ws = web.WebSocketResponse()
        await ws.prepare(self.request)

        async for msg in ws:
            if msg.type == aiohttp.WSMsgType.text:
                try:
                    message = ujson.loads(msg.data)
                except ValueError:
                    logger.warning('Invalid websocket payload, ignored: {}'.format(
                        msg.data))
                    continue
                if message['op'] == 'close':
                    await ws.close()
                elif message['op'].lower() == 'get':
                    txn = await tm.begin(request=self.request)
                    try:
                        await self.handle_ws_request(ws, message)
                    except Exception:
                        logger.error('Exception on ws', exc_info=True)
                    finally:
                        # only currently support GET requests which are *never*
                        # supposed to be commits
                        await tm.abort(txn=txn)
            elif msg.type == aiohttp.WSMsgType.error:
                logger.debug('ws connection closed with exception {0:s}'
                             .format(ws.exception()))

        logger.debug('websocket connection closed')

        return {}
Exemplo n.º 6
0
 async def wait_for_tasks(self):
     for task in asyncio.Task.all_tasks():
         if task.done():
             continue
         try:
             logger.info(f'Waiting for {task._coro.__qualname__} to finish')
             try:
                 await asyncio.wait_for(asyncio.shield(task), 1)
             except asyncio.TimeoutError:
                 logger.warning(f'Timeout for {task._coro.__qualname__}')
         except (AttributeError, KeyError):
             pass
Exemplo n.º 7
0
 async def wait_for_tasks(self):
     for task in asyncio.Task.all_tasks():
         if task.done():
             continue
         try:
             logger.info(f'Waiting for {task._coro.__qualname__} to finish')
             try:
                 await asyncio.wait_for(asyncio.shield(task), 1)
             except asyncio.TimeoutError:
                 logger.warning(f'Timeout for {task._coro.__qualname__}')
         except (AttributeError, KeyError):
             pass
Exemplo n.º 8
0
def get_settings(configuration, overrides=None):
    if configuration == 'config.yaml' and not os.path.exists(configuration):
        # try config.json as well...
        configuration = 'config.json'
    if os.path.exists(configuration):
        with open(configuration, 'r') as config:
            if configuration.lower().endswith('.json'):
                try:
                    settings = json.load(config)
                except json.decoder.JSONDecodeError:
                    logger.warning('Could not parse json configuration {}'.format(
                        configuration))
                    raise
            else:
                # should be yaml then...
                settings = yaml.load(config)
        settings['__file__'] = configuration
    else:
        try:
            settings = json.loads(configuration)
        except json.decoder.JSONDecodeError:
            # try with yaml parser too..
            try:
                settings = yaml.load(configuration)
                # will also parse strings...
                if isinstance(settings, str):
                    settings = None
            except yaml.parser.ParserError:
                settings = None

    if settings is None or settings == configuration:
        if 'logged' not in MISSING_SETTINGS:
            logger.warning(f'No configuration file found. '
                           f'Using default settings.')
        MISSING_SETTINGS['logged'] = True
        settings = MISSING_SETTINGS.copy()

    for override in overrides or []:
        if '=' not in override:
            raise Exception(f'Invalid configuration {override}')
        name, _, value = override.partition('=')
        context = settings
        parts = name.split('.')
        for part in parts[:-1]:
            if part not in context:
                context[part] = {}
            context = context[part]
        context[parts[-1]] = value
    return settings
Exemplo n.º 9
0
 async def cleanup(self, app):
     try:
         await app.shutdown()
     except Exception:
         logger.warning("Unhandled error cleanup tasks", exc_info=True)
     for task in asyncio.Task.all_tasks():
         if task.done():
             continue
         if "cleanup" in task._coro.__qualname__:
             continue
         try:
             logger.info(f"Waiting for {task._coro.__qualname__} to finish")
             try:
                 await asyncio.wait_for(asyncio.shield(task), 1)
             except asyncio.TimeoutError:
                 logger.warning(f"Timeout for {task._coro.__qualname__}")
         except (AttributeError, KeyError):
             pass
Exemplo n.º 10
0
def get_settings(configuration):
    configuration_filename = configuration
    if configuration == 'config.yaml' and not os.path.exists(configuration):
        # try config.json as well...
        configuration_filename = 'config.json'
    if os.path.exists(configuration_filename):
        with open(configuration_filename, 'r') as config:
            if configuration_filename.lower().endswith('.json'):
                settings = json.load(config)
            else:
                # should be yaml then...
                settings = yaml.load(config)
    else:
        logger.warning('Could not find the configuration file {}. Using default settings.'.format(
            configuration
        ))
        settings = MISSING_SETTINGS.copy()
    return settings
Exemplo n.º 11
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)
Exemplo n.º 12
0
 async def cleanup(self, app):
     try:
         app.freeze()
         await app.on_cleanup.send(app)
     except Exception:
         logger.warning('Unhandled error cleanup tasks', exc_info=True)
     for task in asyncio.Task.all_tasks():
         if task.done():
             continue
         if 'cleanup' in task._coro.__qualname__:
             continue
         try:
             logger.info(f'Waiting for {task._coro.__qualname__} to finish')
             try:
                 await asyncio.wait_for(asyncio.shield(task), 1)
             except asyncio.TimeoutError:
                 logger.warning(f'Timeout for {task._coro.__qualname__}')
         except (AttributeError, KeyError):
             pass
Exemplo n.º 13
0
def get_settings(configuration, overrides=None):
    if configuration == "config.yaml" and not os.path.exists(configuration):
        # try config.json as well...
        configuration = "config.json"
    if os.path.exists(configuration):
        with open(configuration, "r") as config:
            if configuration.lower().endswith(".json"):
                try:
                    settings = json.load(config)
                except json.decoder.JSONDecodeError:
                    logger.warning(
                        "Could not parse json configuration {}".format(
                            configuration))
                    raise
            else:
                # should be yaml then...
                settings = yaml.load(config, Loader=yaml.FullLoader)
        settings["__file__"] = configuration
    else:
        try:
            settings = json.loads(configuration)
        except json.decoder.JSONDecodeError:
            # try with yaml parser too..
            try:
                settings = yaml.load(configuration, Loader=yaml.FullLoader)
                # will also parse strings...
                if isinstance(settings, str):
                    settings = None
            except yaml.parser.ParserError:
                settings = None

    if settings is None or settings == configuration:
        if "logged" not in MISSING_SETTINGS:
            logger.warning(
                f"No configuration file found. Using default settings with DUMMY_FILE db."
            )
        MISSING_SETTINGS["logged"] = True
        settings = MISSING_SETTINGS.copy()

    for override in overrides or []:
        if "=" not in override:
            raise Exception(f"Invalid configuration {override}")
        name, _, value = override.partition("=")
        context = settings
        parts = name.split(".")
        for part in parts[:-1]:
            if part not in context:
                context[part] = {}
            context = context[part]
        context[parts[-1]] = value

    for env_name in os.environ.keys():
        orig_env_name = env_name
        env_name = env_name.lower()
        if not env_name.startswith("g_"):
            continue
        name = env_name[2:]
        value = os.environ[orig_env_name]
        if len(value) > 0 and value[0] in ("{", "["):
            value = json.loads(value)
        context = settings
        parts = name.split("__")
        for part in parts[:-1]:
            if part not in context:
                context[part] = {}
            context = context[part]
        context[parts[-1]] = value

    return settings
Exemplo n.º 14
0
def get_settings(configuration, overrides=None):
    if configuration == 'config.yaml' and not os.path.exists(configuration):
        # try config.json as well...
        configuration = 'config.json'
    if os.path.exists(configuration):
        with open(configuration, 'r') as config:
            if configuration.lower().endswith('.json'):
                try:
                    settings = json.load(config)
                except json.decoder.JSONDecodeError:
                    logger.warning('Could not parse json configuration {}'.format(
                        configuration))
                    raise
            else:
                # should be yaml then...
                settings = yaml.load(config, Loader=yaml.FullLoader)
        settings['__file__'] = configuration
    else:
        try:
            settings = json.loads(configuration)
        except json.decoder.JSONDecodeError:
            # try with yaml parser too..
            try:
                settings = yaml.load(configuration, Loader=yaml.FullLoader)
                # will also parse strings...
                if isinstance(settings, str):
                    settings = None
            except yaml.parser.ParserError:
                settings = None

    if settings is None or settings == configuration:
        if 'logged' not in MISSING_SETTINGS:
            logger.warning(f'No configuration file found. '
                           f'Using default settings.')
        MISSING_SETTINGS['logged'] = True
        settings = MISSING_SETTINGS.copy()

    for override in overrides or []:
        if '=' not in override:
            raise Exception(f'Invalid configuration {override}')
        name, _, value = override.partition('=')
        context = settings
        parts = name.split('.')
        for part in parts[:-1]:
            if part not in context:
                context[part] = {}
            context = context[part]
        context[parts[-1]] = value

    for env_name in os.environ.keys():
        if not env_name.startswith('G_'):
            continue
        name = env_name[2:].lower()
        value = os.environ[env_name]
        if value[0] in ('{', '['):
            value = json.loads(value)
        context = settings
        parts = name.split('__')
        for part in parts[:-1]:
            if part not in context:
                context[part] = {}
            context = context[part]
        context[parts[-1]] = value

    return settings
Exemplo n.º 15
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:
            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:]

        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

        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.warning(
                        "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.warning(
                    "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)

        if rendered is not None:
            return MatchInfo(resource, request, view, rendered)
        else:
            return None