예제 #1
0
async def test_create_annotation(db, guillotina_main):
    db = await get_database("db")
    login()

    async with transaction(db=db):
        container = await create_content_in_container(db,
                                                      "Container",
                                                      "container",
                                                      title="Container")
        ob = await create_content_in_container(container, "Item", "foobar")

        annotations = IAnnotations(ob)
        data = AnnotationData()
        data["foo"] = "bar"
        await annotations.async_set("foobar", data)

    async with transaction(db=db):
        container = await db.async_get("container")
        ob = await container.async_get("foobar")
        annotations = IAnnotations(ob)
        assert "foobar" in (await annotations.async_keys())
        await annotations.async_del("foobar")

    async with transaction(db=db):
        container = await db.async_get("container")
        ob = await container.async_get("foobar")
        annotations = IAnnotations(ob)
        assert "foobar" not in (await annotations.async_keys())
        await container.async_del("foobar")
        await db.async_del("container")
예제 #2
0
async def test_create_annotation(db, guillotina_main):
    root = get_utility(IApplication, name='root')
    db = root['db']
    request = get_mocked_request(db)
    login(request)

    async with managed_transaction(request=request, write=True):
        container = await create_content_in_container(
            db, 'Container', 'container', request=request,
            title='Container')
        ob = await create_content_in_container(
            container, 'Item', 'foobar', request=request)

        annotations = IAnnotations(ob)
        data = AnnotationData()
        data['foo'] = 'bar'
        await annotations.async_set('foobar', data)

    async with managed_transaction(request=request, write=True):
        container = await db.async_get('container')
        ob = await container.async_get('foobar')
        annotations = IAnnotations(ob)
        assert 'foobar' in (await annotations.async_keys())
        await annotations.async_del('foobar')

    async with managed_transaction(request=request, write=True):
        container = await db.async_get('container')
        ob = await container.async_get('foobar')
        annotations = IAnnotations(ob)
        assert 'foobar' not in (await annotations.async_keys())
        await container.async_del('foobar')
        await db.async_del('container')
예제 #3
0
async def test_create_annotation(db, guillotina_main):
    db = await get_database('db')
    login()

    async with transaction(db=db):
        container = await create_content_in_container(db,
                                                      'Container',
                                                      'container',
                                                      title='Container')
        ob = await create_content_in_container(container, 'Item', 'foobar')

        annotations = IAnnotations(ob)
        data = AnnotationData()
        data['foo'] = 'bar'
        await annotations.async_set('foobar', data)

    async with transaction(db=db):
        container = await db.async_get('container')
        ob = await container.async_get('foobar')
        annotations = IAnnotations(ob)
        assert 'foobar' in (await annotations.async_keys())
        await annotations.async_del('foobar')

    async with transaction(db=db):
        container = await db.async_get('container')
        ob = await container.async_get('foobar')
        annotations = IAnnotations(ob)
        assert 'foobar' not in (await annotations.async_keys())
        await container.async_del('foobar')
        await db.async_del('container')
예제 #4
0
 async def get_annotation(self, context, annotation_index, create=True):
     annotation_name = self.get_annotation_name(annotation_index)
     annotations_container = IAnnotations(context)
     annotation = annotations_container.get(annotation_name, _default)
     if annotation is _default:
         annotation = await annotations_container.async_get(
             annotation_name, _default)
     if annotation is _default:
         if not create:
             return
         # create
         annotation = AnnotationData()
         annotation.update({'items': []})
         await annotations_container.async_set(annotation_name, annotation)
     if annotation_index not in self.annotations_metadata:
         self.annotations_metadata[annotation_index] = {}
     return annotation
예제 #5
0
 async def _get_registry_or_create(self):
     annotations_container = IAnnotations(self.context)
     object_settings = await annotations_container.async_get("default"
                                                             )  # noqa
     if object_settings is None:
         # need to create annotation...
         object_settings = AnnotationData()
         await annotations_container.async_set("default", object_settings)
     return object_settings
예제 #6
0
 async def get_annotation(self, context, annotation_index, create=True):
     annotation_name = self.get_annotation_name(annotation_index)
     annotations_container = IAnnotations(context)
     annotation = annotations_container.get(annotation_name, _default)
     if annotation is _default:
         annotation = await annotations_container.async_get(
             annotation_name, _default)
     if annotation is _default:
         if not create:
             return
         # create
         annotation = AnnotationData()
         annotation.update({
             'items': []
         })
         await annotations_container.async_set(annotation_name, annotation)
     if annotation_index not in self.annotations_metadata:
         self.annotations_metadata[annotation_index] = {}
     return annotation
예제 #7
0
 async def get_annotation(self,
                          context: IBaseObject,
                          annotation_index: int,
                          create: bool = True) -> Optional[IAnnotationData]:
     annotation_name = self.get_annotation_name(annotation_index)
     annotations_container = IAnnotations(context)
     annotation = annotations_container.get(annotation_name, _default)
     if annotation is _default:
         annotation = await annotations_container.async_get(
             annotation_name, _default)
     if annotation is _default:
         if not create:
             return None
         # create
         annotation = AnnotationData()
         annotation.update({"items": []})
         await annotations_container.async_set(annotation_name, annotation)
     if annotation_index not in self.annotations_metadata:
         self.annotations_metadata[annotation_index] = {}
     return annotation
예제 #8
0
 async def get_registry(self, refresh=False):
     if (refresh and self.object_settings is not None):
         txn = get_transaction(self.request)
         await txn.refresh(self.object_settings)
     annotations_container = IAnnotations(self.context)
     self.object_settings = await annotations_container.async_get('default')
     if self.object_settings is None:
         # need to create annotation...
         self.object_settings = AnnotationData()
         await annotations_container.async_set('default',
                                               self.object_settings)
     return self.object_settings
예제 #9
0
 async def load(self, create=False):
     annotations_container = IAnnotations(self.__dict__['context'])
     annotations = {}
     try:
         annotations = await annotations_container.async_get(
             self.__annotations_data_key)
     except KeyError:
         if create:
             annotations = AnnotationData()
             await annotations_container.async_set(
                 self.__annotations_data_key, annotations)
     self.__dict__['data'] = annotations
예제 #10
0
    async def load(self, create=False):
        annotations_container = IAnnotations(self.__dict__["context"])
        data = annotations_container.get(self.__annotations_data_key__, _default)
        if data is not _default:
            # data is already preloaded, we do not need to get from db again...
            self.__dict__["data"] = data
            return

        annotations = await annotations_container.async_get(self.__annotations_data_key__)
        if annotations is None:
            if create:
                annotations = AnnotationData()
                await annotations_container.async_set(self.__annotations_data_key__, annotations)
            else:
                annotations = {}  # fallback, assumed only for reading here...
        self.__dict__["data"] = annotations
예제 #11
0
    async def get_annotation(self,
                             context,
                             key=None,
                             anno_id=None,
                             create=True) -> typing.Optional[AnnotationData]:
        if anno_id is None:
            bidx, bucket = self._find_bucket(key)
            annotation_name = self.get_annotation_name(bucket["id"])
        else:
            annotation_name = self.get_annotation_name(anno_id)

        annotations_container = IAnnotations(context)
        annotation = annotations_container.get(annotation_name, _default)
        if annotation is _default:
            annotation = await annotations_container.async_get(
                annotation_name, _default)
        if annotation is _default:
            if not create:
                return None
            annotation = AnnotationData({"keys": [], "values": []})
            await annotations_container.async_set(annotation_name, annotation)
        return annotation
예제 #12
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:
            raise PreconditionFailed(
                context,
                'Could not find destination object',
            )
    else:
        destination_ob = context.__parent__

    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' in data:
        new_id = data['new_id']
        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}'

    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)

    data['id'] = new_id
    await notify(
        ObjectDuplicatedEvent(new_obj,
                              context,
                              destination_ob,
                              new_id,
                              payload=data))

    get = DefaultGET(new_obj, request)
    return await get()
예제 #13
0
async def test_txn_uses_cached_hits_on_annotations(redis_container,
                                                   guillotina_main):
    util = get_utility(ICacheUtility)
    await util.initialize()

    async with transaction(db=await get_database("db")) as txn:
        root = await txn.manager.get_root()
        container = await create_container(root, "container")

        with pytest.raises(KeyError):
            # should set in cache as empty though
            await txn.get_annotation(container, "foobar")
        # should be registered as cache miss
        assert txn._cache._hits == 0
        assert txn._cache._misses == 2

        with pytest.raises(KeyError):
            # do again, should be hit this time
            await txn.get_annotation(container, "foobar")

        assert txn._cache._hits == 1
        assert txn._cache._misses == 2

        # now set a value for it and we'll retrieve it again
        annotations_container = IAnnotations(container)
        adata = AnnotationData()
        await annotations_container.async_set("foobar", adata)

    async with transaction(db=await get_database("db")) as txn:
        # everything here should be hits!
        root = await txn.manager.get_root()
        container = await root.async_get("container")

        adata = await txn.get_annotation(container, "foobar")
        # should be registered as cache miss
        assert txn._cache._hits == 2
        assert txn._cache._misses == 0

    async with transaction(db=await get_database("db")) as txn:
        # now, edit the value
        root = await txn.manager.get_root()
        container = await root.async_get("container")

        adata = await txn.get_annotation(container, "foobar")
        adata["foo"] = "bar"
        adata.register()
        # should be registered as cache miss
        assert txn._cache._hits == 2
        assert txn._cache._misses == 0

    async with transaction(db=await get_database("db")) as txn:
        # everything here should be hits!
        root = await txn.manager.get_root()
        container = await root.async_get("container")

        adata = await txn.get_annotation(container, "foobar")
        assert adata["foo"] == "bar"
        # should be registered as cache miss
        assert txn._cache._hits == 2
        assert txn._cache._misses == 0

    # same again, but clear cache implementation
    await util.clear()

    async with transaction(db=await get_database("db")) as txn:
        # everything here should be hits!
        root = await txn.manager.get_root()
        container = await root.async_get("container")

        adata = await txn.get_annotation(container, "foobar")
        assert adata["foo"] == "bar"
        # should be registered as cache miss
        assert txn._cache._hits == 0
        assert txn._cache._misses == 2
예제 #14
0
async def duplicate(
    context: IResource,
    destination: Optional[Union[IResource, str]] = None,
    new_id: Optional[str] = None,
    check_permission: bool = True,
    reset_acl: bool = False,
) -> IResource:
    if destination is not None:
        if isinstance(destination, str):
            destination_ob = None
            if destination.startswith("/"):
                container = task_vars.container.get()
                if container:
                    try:
                        destination_ob = await navigate_to(container, destination)
                    except KeyError:
                        pass
            else:
                try:
                    destination_ob = await get_object_by_uid(destination)
                except KeyError:
                    pass
        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:
        policy = get_security_policy()
        if not policy.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

    creators = context.creators
    contributors = context.contributors
    user_id = get_authenticated_user_id()
    if reset_acl:
        creators = [user_id]
        contributors = [user_id]
    new_obj = await create_content_in_container(
        destination_ob,
        context.type_name,
        new_id,
        id=new_id,
        creators=creators,
        contributors=contributors,
        check_security=check_permission,
        check_constraints=True,
    )
    for key in context.__dict__.keys():
        if key.startswith("__") or key.startswith("_BaseObject"):
            continue
        if key in ("id", "creators", "contributors"):
            continue
        new_obj.__dict__[key] = context.__dict__[key]

    if reset_acl:
        new_obj.__acl__ = None
        get_owner = get_utility(IGetOwner)
        roleperm = IPrincipalRoleManager(new_obj)
        owner = await get_owner(new_obj, user_id)
        if owner is not None:
            roleperm.assign_role_to_principal("guillotina.Owner", owner)
    else:
        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
예제 #15
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):
            container = task_vars.container.get()
            if container:
                destination_ob = await navigate_to(container, destination)
            else:
                raise PreconditionFailed(context, "Could not find destination object")
        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:
        policy = get_security_policy()
        if not policy.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
예제 #16
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