Ejemplo n.º 1
0
async def can_i_do(context, request):
    if 'permission' not in request.query and 'permissions' not in request.query:
        raise PreconditionFailed(context, 'No permission param')
    interaction = IInteraction(request)
    if 'permissions' in request.GET:
        results = {}
        for perm in request.GET['permissions'].split(','):
            results[perm] = interaction.check_permission(perm, context)
        return results
    else:
        return interaction.check_permission(request.GET['permission'], context)
Ejemplo n.º 2
0
async def resolve_uid(context, request):
    uid = request.matchdict['uid']
    ob = await get_object_by_oid(uid)
    if ob is None:
        return HTTPNotFound(content={'reason': f'Could not find uid: {uid}'})
    interaction = IInteraction(request)
    if interaction.check_permission('guillotina.AccessContent', ob):
        return HTTPMovedPermanently(get_object_url(ob, request))
    else:
        # if a user doesn't have access to it, they shouldn't know anything about it
        return HTTPNotFound(content={'reason': f'Could not find uid: {uid}'})
Ejemplo n.º 3
0
        async def available_actions(self, request):
            security = IInteraction(request)
            for action_name, action in self.actions.items():
                add = False
                if 'check_permission' in action and security.check_permission(
                        action['check_permission'], self.context):
                    add = True
                elif 'check_permission' not in action:
                    add = True

                if add:
                    yield action_name, action
Ejemplo n.º 4
0
    def check_permission(self, permission_name):
        if permission_name is None:
            return True

        if permission_name not in self.permission_cache:
            permission = query_utility(IPermission, name=permission_name)
            if permission is None:
                self.permission_cache[permission_name] = True
            else:
                security = IInteraction(self.request)
                self.permission_cache[permission_name] = bool(
                    security.check_permission(permission.id, self.context))
        return self.permission_cache[permission_name]
Ejemplo n.º 5
0
    def check_permission(self, permission_name):
        if permission_name is None:
            return True

        if permission_name not in self.permission_cache:
            permission = query_utility(IPermission,
                                       name=permission_name)
            if permission is None:
                self.permission_cache[permission_name] = True
            else:
                security = IInteraction(self.request)
                self.permission_cache[permission_name] = bool(
                    security.check_permission(permission.id, self.context))
        return self.permission_cache[permission_name]
Ejemplo n.º 6
0
        async def do_action(self, request, action, comments):
            available_actions = self.actions
            if action not in available_actions:
                raise KeyError('Unavailable action')

            action_def = available_actions[action]
            security = IInteraction(request)
            if 'check_permission' in action_def and not security.check_permission(
                    action_def['check_permission'], self.context):
                raise HTTPUnauthorized()

            # Change permission
            new_state = action_def['to']

            if 'set_permission' in self.states[new_state]:
                await apply_sharing(self.context,
                                    self.states[new_state]['set_permission'])

            # Write history
            user = get_authenticated_user_id(request)
            history = {
                'actor': user,
                'comments': comments,
                'time': datetime.datetime.now(),
                'title': action_def['title'],
                'type': 'workflow',
                'data': {
                    'action': action,
                    'review_state': new_state,
                }
            }

            cms_behavior = ICMSBehavior(self.context)
            await cms_behavior.load()
            cms_behavior.review_state = new_state

            cms_behavior.history.append(history)
            cms_behavior._p_register()

            await notify(
                WorkflowChangedEvent(self.context, self, action, comments))
            return history
Ejemplo n.º 7
0
    async def __call__(self):
        result = await super(SerializeFolderToJson, self).__call__()

        security = IInteraction(self.request)
        length = await self.context.async_len()

        if length > MAX_ALLOWED or length == 0:
            result['items'] = []
        else:
            result['items'] = []
            async for ident, member in self.context.async_items():
                if not ident.startswith('_') and bool(
                        security.check_permission('guillotina.AccessContent',
                                                  member)):
                    result['items'].append(await getMultiAdapter(
                        (member, self.request),
                        IResourceSerializeToJsonSummary)())
        result['length'] = length

        return result
Ejemplo n.º 8
0
    async def __call__(self, include=[], omit=[]):
        result = await super(SerializeFolderToJson, self).__call__(include=include, omit=omit)

        security = IInteraction(self.request)
        length = await self.context.async_len()

        if length > MAX_ALLOWED or length == 0:
            result['items'] = []
        else:
            result['items'] = []
            async for ident, member in self.context.async_items(suppress_events=True):
                if not ident.startswith('_') and bool(
                        security.check_permission(
                        'guillotina.AccessContent', member)):
                    result['items'].append(
                        await get_multi_adapter(
                            (member, self.request),
                            IResourceSerializeToJsonSummary)())
        result['length'] = length

        return result
Ejemplo n.º 9
0
async def move(context: IResource,
               destination: Union[IResource, str] = None,
               new_id: str = None,
               check_permission: bool = True) -> None:
    if destination is None:
        destination_ob = context.__parent__
    else:
        if isinstance(destination, str):
            request = get_current_request()
            try:
                destination_ob = await navigate_to(request.container,
                                                   destination)
            except KeyError:
                destination_ob = None
        else:
            destination_ob = destination

    if destination_ob is None:
        raise PreconditionFailed(context, 'Could not find destination object')
    old_id = context.id
    if new_id is not None:
        context.id = context.__name__ = new_id
    else:
        new_id = context.id

    if check_permission:
        request = get_current_request()
        security = IInteraction(request)
        if not security.check_permission('guillotina.AddContent',
                                         destination_ob):
            raise PreconditionFailed(
                context, 'You do not have permission to add content to the '
                'destination object')

    if await destination_ob.async_contains(new_id):
        raise PreconditionFailed(
            context, f'Destination already has object with the id {new_id}')

    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={
                                   'id': new_id,
                                   'destination': destination
                               }))

    context.__parent__ = destination_ob
    context._p_register()

    await notify(
        ObjectMovedEvent(context,
                         original_parent,
                         old_id,
                         destination_ob,
                         new_id,
                         payload={
                             'id': new_id,
                             'destination': destination
                         }))

    cache_keys += txn._cache.get_cache_keys(context, 'added')
    await txn._cache.delete_all(cache_keys)
Ejemplo n.º 10
0
async def duplicate(context: IResource,
                    destination: Union[IResource, str] = None,
                    new_id: str = None,
                    check_permission: bool = True) -> IResource:
    if destination is not None:
        if isinstance(destination, str):
            request = get_current_request()
            destination_ob = await navigate_to(request.container, destination)
        else:
            destination_ob = destination

        if destination_ob is None:
            raise PreconditionFailed(
                context,
                'Could not find destination object',
            )
    else:
        destination_ob = context.__parent__

    if check_permission:
        request = get_current_request()
        security = IInteraction(request)
        if not security.check_permission('guillotina.AddContent',
                                         destination_ob):
            raise PreconditionFailed(
                context,
                'You do not have permission to add content to '
                'the destination object',
            )

    if new_id is not None:
        if await destination_ob.async_contains(new_id):
            raise PreconditionFailed(
                context,
                f'Destination already has object with the id {new_id}')
    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}'

    from guillotina.content import create_content_in_container
    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__
    for behavior in context.__behaviors__:
        new_obj.add_behavior(behavior)

    # 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.__gannotations__.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={
                                  'id': new_id,
                                  'destination': destination,
                              }))
    return new_obj
Ejemplo n.º 11
0
    async def real_resolve(self, request):
        """Main function to resolve a request."""
        request._futures = {}

        security = IInteraction(request)

        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()
            # XXX should only should traceback if in some sort of dev mode?
            raise HTTPBadRequest(text=json.dumps(data))

        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)

        translator = queryMultiAdapter(
            (language_object, resource, request),
            ITranslated)
        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 = queryMultiAdapter(
                (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 Exception as e:
                    logger.error("Exception on view execution", exc_info=e,
                                 request=request)
                    return None

        permission = getUtility(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()

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

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

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