Beispiel #1
0
    async def __call__(self):
        """ data input : { 'interface': 'INTERFACE' }"""
        if not hasattr(self.request, 'container_settings'):
            return ErrorResponse('BadRequest', _("Not in a container request"))

        data = await self.request.json()
        interface = data.get('interface', None)
        initial_values = data.get('initial_values', {})
        if interface is None:
            return ErrorResponse('InvalidRequest', 'Non existent Interface')

        registry = self.request.container_settings
        iObject = import_class(interface)
        registry.register_interface(iObject)
        config = registry.for_interface(iObject)

        # Initialize values
        # If its defined on the guillotina.schema default will not be overwritten
        #  you will need to PATCH
        for key, field in get_fields(iObject).items():
            if key in initial_values and getattr(config, key,
                                                 _marker) == _marker:
                # We don't have a value
                config[key] = initial_values[key]

        return Response(response={}, status=201)
Beispiel #2
0
    async def __call__(self):
        if self.key is _marker:
            # No option to write the root of registry
            return ErrorResponse('InvalidRequest', 'Needs the registry key')

        data = await self.request.json()
        if 'value' in data:
            value = data['value']
        else:
            value = data

        assert '.' in self.key, 'Registry key must be dotted.iface.name.fieldname'  # noqa
        iface, name = self.key.rsplit('.', 1)
        iface = resolve_dotted_name(iface)
        field = iface[name]

        try:
            new_value = get_adapter((field),
                                    IJSONToValue,
                                    args=[value, self.context])
        except ComponentLookupError:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     str(self.field)),
                                 status=501)

        try:
            self.request.container_settings[self.key] = new_value
        except DeserializationError as e:
            return ErrorResponse('DeserializationError',
                                 str(e),
                                 exc=e,
                                 status=400)

        return Response(response='', status=204)
Beispiel #3
0
    async def __call__(self):
        data = await self.get_data()

        if 'id' in data and data['id'] != self.context.id:
            return ErrorResponse('DeserializationError',
                                 'Not allowed to change id of content.',
                                 status=412)

        behaviors = data.get('@behaviors', None)
        for behavior in behaviors or ():
            self.context.add_behavior(behavior)

        deserializer = query_multi_adapter((self.context, self.request),
                                           IResourceDeserializeFromJson)
        if deserializer is None:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     self.context.type_name),
                                 status=412)

        try:
            await deserializer(data)
        except DeserializationError as e:
            return ErrorResponse('DeserializationError', str(e), status=422)

        await notify(ObjectModifiedEvent(self.context, payload=data))

        return Response(response='', status=204)
Beispiel #4
0
    async def __call__(self):
        data = await self.request.json()
        if '@type' not in data or data['@type'] != 'Container':
            return ErrorResponse('NotAllowed',
                                 'can not create this type %s' % data['@type'],
                                 status=401)

        if 'id' not in data:
            return ErrorResponse('NotAllowed', 'We need an id', status=401)

        if not data.get('title'):
            data['title'] = data['id']

        if 'description' not in data:
            data['description'] = ''

        value = await self.context.async_contains(data['id'])

        if value:
            # Already exist
            return ErrorResponse('ConflictId',
                                 'Container with id already exists',
                                 status=409)

        container = await create_content('Container',
                                         id=data['id'],
                                         title=data['title'],
                                         description=data['description'])

        # Special case we don't want the parent pointer
        container.__name__ = data['id']

        await self.context.async_set(data['id'], container)
        await container.install()

        self.request._container_id = container.__name__
        self.request.container = container

        user = get_authenticated_user_id(self.request)

        # Local Roles assign owner as the creator user
        roleperm = IPrincipalRoleManager(container)
        roleperm.assign_role_to_principal('guillotina.Owner', user)

        await notify(
            ObjectAddedEvent(container,
                             self.context,
                             container.__name__,
                             payload=data))

        resp = {'@type': 'Container', 'id': data['id'], 'title': data['title']}
        headers = {'Location': self.request.path + data['id']}

        return Response(response=resp, headers=headers)
Beispiel #5
0
async def uninstall(context, request):
    data = await request.json()
    id_to_install = data.get('id', None)
    if id_to_install not in app_settings['available_addons']:
        return ErrorResponse('RequiredParam',
                             _("Property 'id' is required to be valid"))

    registry = request.container_settings
    config = registry.for_interface(IAddons)

    if id_to_install not in config['enabled']:
        return ErrorResponse('Duplicate', _("Addon not installed"))

    handler = app_settings['available_addons'][id_to_install]['handler']
    await apply_coroutine(handler.uninstall, context, request)
    config['enabled'] -= {id_to_install}
Beispiel #6
0
    async def __call__(self):
        data = await self.request.json()
        if '@type' not in data and data['@type'] != 'Site':
            return ErrorResponse('NotAllowed',
                                 'can not create this type %s' % data['@type'],
                                 status=401)

        if 'title' not in data and not data['title']:
            return ErrorResponse('NotAllowed', 'We need a title', status=401)

        if 'id' not in data:
            return ErrorResponse('NotAllowed', 'We need an id', status=401)

        if 'description' not in data:
            data['description'] = ''

        value = await self.context.async_contains(data['id'])

        if value:
            # Already exist
            return ErrorResponse('NotAllowed', 'Duplicate id', status=401)

        site = await create_content('Site',
                                    id=data['id'],
                                    title=data['title'],
                                    description=data['description'])

        # Special case we don't want the parent pointer
        site.__name__ = data['id']

        await self.context.async_set(data['id'], site)
        await site.install()

        self.request._site_id = site.__name__

        user = get_authenticated_user_id(self.request)

        # Local Roles assign owner as the creator user
        roleperm = IPrincipalRoleManager(site)
        roleperm.assign_role_to_principal('guillotina.Owner', user)

        await notify(ObjectAddedEvent(site, self.context, site.__name__))

        resp = {'@type': 'Site', 'id': data['id'], 'title': data['title']}
        headers = {'Location': self.request.path + data['id']}

        return Response(response=resp, headers=headers)
Beispiel #7
0
def generate_error_response(e, request, error, status=400):
    # We may need to check the roles of the users to show the real error
    eid = uuid.uuid4().hex
    message = _('Error on execution of view') + ' ' + eid
    user = get_authenticated_user_id(request)
    extra = {'r': _url(request), 'u': user}
    logger.error(message, exc_info=e, extra=extra)

    return ErrorResponse(error, message, status)
Beispiel #8
0
    async def __call__(self):
        data = await self.get_data()
        behaviors = data.get('@behaviors', None)
        for behavior in behaviors or ():
            self.context.add_behavior(behavior)

        deserializer = queryMultiAdapter((self.context, self.request),
                                         IResourceDeserializeFromJson)
        if deserializer is None:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     self.context.type_name),
                                 status=501)

        try:
            await deserializer(data)
        except DeserializationError as e:
            return ErrorResponse('DeserializationError', str(e), status=400)

        await notify(ObjectModifiedEvent(self.context, payload=data))

        return Response(response={}, status=204)
    async def query(
            self, container, query,
            doc_type=None, size=10, request=None):
        """
        transform into query...
        right now, it's just passing through into elasticsearch
        """
        t1 = time.time()
        if request is None:
            request = get_current_request()
        q = await self._build_security_query(
            container, query, doc_type, size, request)
        result = await self.conn.search(**q)
        if result.get('_shards', {}).get('failed', 0) > 0:
            logger.warning(f'Error running query: {result["_shards"]}')
            error_message = 'Unknown'
            for failure in result["_shards"].get('failures') or []:
                error_message = failure['reason']
            return ErrorResponse('QueryError', error_message, status=488)
        items = self._get_items_from_result(container, request, result)
        final = {
            'items_count': result['hits']['total'],
            'member': items
        }
        if 'aggregations' in result:
            final['aggregations'] = result['aggregations']
        if 'suggest' in result:
            final['suggest'] = result['suggest']
        if 'profile' in result:
            final['profile'] = result['profile']

        tdif = time.time() - t1
        logger.debug(f'Time ELASTIC {tdif}')
        await notify(SearchDoneEvent(
            query, result['hits']['total'], request, tdif))
        return final
Beispiel #10
0
 async def __call__(self):
     return ErrorResponse('NotImplemented',
                          'Function not implemented',
                          status=501)
Beispiel #11
0
async def duplicate(context, request):
    try:
        data = await request.json()
    except Exception:
        data = {}
    destination = data.get('destination')
    if destination is not None:
        destination_ob = await navigate_to(request.container, destination)
        if destination_ob is None:
            return ErrorResponse('Configuration',
                                 'Could not find destination object',
                                 status=400)
    else:
        destination_ob = context.__parent__

    security = IInteraction(request)
    if not security.check_permission('guillotina.AddContent', destination_ob):
        return ErrorResponse(
            'Configuration',
            'You do not have permission to add content to the destination object',
            status=400)

    if 'new_id' in data:
        new_id = data['new_id']
        if await destination_ob.async_contains(new_id):
            return ErrorResponse(
                'Configuration',
                f'Destination already has object with the id {new_id}',
                status=400)
    else:
        count = 1
        new_id = f'{context.id}-duplicate-{count}'
        while await destination_ob.async_contains(new_id):
            count += 1
            new_id = f'{context.id}-duplicate-{count}'

    new_obj = await create_content_in_container(
        destination_ob,
        context.type_name,
        new_id,
        id=new_id,
        creators=context.creators,
        contributors=context.contributors)

    for key in context.__dict__.keys():
        if key.startswith('__') or key.startswith('_BaseObject'):
            continue
        if key in ('id', ):
            continue
        new_obj.__dict__[key] = context.__dict__[key]
    new_obj.__acl__ = context.__acl__
    new_obj.__behaviors__ = context.__behaviors__

    # need to copy annotation data as well...
    # load all annotations for context
    [b for b in await get_all_behaviors(context, load=True)]
    annotations_container = IAnnotations(new_obj)
    for anno_id, anno_data in context.__annotations__.items():
        new_anno_data = AnnotationData()
        for key, value in anno_data.items():
            new_anno_data[key] = value
        await annotations_container.async_set(anno_id, new_anno_data)

    await notify(
        ObjectDuplicatedEvent(new_obj,
                              context,
                              destination_ob,
                              new_id,
                              payload=data))

    get = DefaultGET(new_obj, request)
    return await get()
Beispiel #12
0
async def move(context, request):
    try:
        data = await request.json()
    except Exception:
        data = {}
    destination = data.get('destination')
    if not destination:
        return ErrorResponse('Configuration',
                             'Missing destination option',
                             status=400)
    try:
        destination_ob = await navigate_to(request.container, destination)
    except KeyError:
        destination_ob = None

    if destination_ob is None:
        return ErrorResponse('Configuration',
                             'Could not find destination object',
                             status=400)
    old_id = context.id
    if 'new_id' in data:
        new_id = data['new_id']
        context.id = context.__name__ = new_id
    else:
        new_id = context.id

    security = IInteraction(request)
    if not security.check_permission('guillotina.AddContent', destination_ob):
        return ErrorResponse(
            'Configuration',
            'You do not have permission to add content to the destination object',
            status=400)

    if await destination_ob.async_contains(new_id):
        return ErrorResponse(
            'Configuration',
            f'Destination already has object with the id {new_id}',
            status=400)

    original_parent = context.__parent__

    txn = get_transaction(request)
    cache_keys = txn._cache.get_cache_keys(context, 'deleted')

    await notify(
        BeforeObjectMovedEvent(context,
                               original_parent,
                               old_id,
                               destination_ob,
                               new_id,
                               payload=data))

    context.__parent__ = destination_ob
    context._p_register()

    await notify(
        ObjectMovedEvent(context,
                         original_parent,
                         old_id,
                         destination_ob,
                         new_id,
                         payload=data))

    cache_keys += txn._cache.get_cache_keys(context, 'added')
    await txn._cache.delete_all(cache_keys)

    absolute_url = queryMultiAdapter((context, request), IAbsoluteURL)
    return {'@url': absolute_url()}
Beispiel #13
0
    async def __call__(self):
        """To create a content."""
        data = await self.get_data()
        type_ = data.get('@type', None)
        id_ = data.get('id', None)
        behaviors = data.get('@behaviors', None)

        if '__acl__' in data:
            # we don't allow to change the permisions on this patch
            del data['__acl__']

        if not type_:
            return ErrorResponse('RequiredParam',
                                 _("Property '@type' is required"))

        # Generate a temporary id if the id is not given
        if not id_:
            new_id = None
        else:
            if not valid_id(id_):
                return ErrorResponse('PreconditionFailed',
                                     str('Invalid id'),
                                     status=412)
            new_id = id_

        user = get_authenticated_user_id(self.request)

        # Create object
        try:
            obj = await create_content_in_container(self.context,
                                                    type_,
                                                    new_id,
                                                    id=new_id,
                                                    creators=(user, ),
                                                    contributors=(user, ))
        except (PreconditionFailed, NotAllowedContentType) as e:
            return ErrorResponse('PreconditionFailed', str(e), status=412)
        except ConflictIdOnContainer as e:
            return ErrorResponse('ConflictId', str(e), status=409)
        except ValueError as e:
            return ErrorResponse('CreatingObject', str(e), status=400)

        for behavior in behaviors or ():
            obj.add_behavior(behavior)

        # Update fields
        deserializer = queryMultiAdapter((obj, self.request),
                                         IResourceDeserializeFromJson)
        if deserializer is None:
            return ErrorResponse('DeserializationError',
                                 'Cannot deserialize type {}'.format(
                                     obj.type_name),
                                 status=501)

        try:
            await deserializer(data, validate_all=True)
        except DeserializationError as e:
            return ErrorResponse('DeserializationError',
                                 str(e),
                                 exc=e,
                                 status=400)

        # Local Roles assign owner as the creator user
        get_owner = getUtility(IGetOwner)
        roleperm = IPrincipalRoleManager(obj)
        roleperm.assign_role_to_principal('guillotina.Owner', await
                                          get_owner(obj, user))

        await notify(ObjectAddedEvent(obj, self.context, obj.id, payload=data))

        absolute_url = queryMultiAdapter((obj, self.request), IAbsoluteURL)

        headers = {
            'Access-Control-Expose-Headers': 'Location',
            'Location': absolute_url()
        }

        serializer = queryMultiAdapter((obj, self.request),
                                       IResourceSerializeToJson)
        response = await serializer()
        return Response(response=response, headers=headers, status=201)
Beispiel #14
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
    message = _('Error on execution of view') + ' ' + eid
    logger.error(message, exc_info=e, eid=eid, request=request)
    return ErrorResponse(error, message, status)