Exemplo n.º 1
0
    def get_or_create_speaker(self, data):
        """
        Returns already created speaker or newly created speaker
        """
        container = self.speakers_container()
        if not container:
            raise Exception('Unable to create a talk proposal. '
                            'Folder "speakers" not available.')
        title = data.get('name', None)

        pc = api.portal.get_tool(name='portal_catalog')
        speakers = pc.unrestrictedSearchResults(
            portal_type='Person',
            path='/'.join(container.getPhysicalPath()),
            Title=title,
        )
        if speakers:
            speaker = speakers[0]._unrestrictedGetObject()
            # self.update_speaker_fields(speaker=speaker, data=data)
            # notify(ObjectModifiedEvent(speaker))
            return speaker

        speaker = self.create_obj(data=data,
                                  type_='Person',
                                  title=title,
                                  container=container)
        if isinstance(speaker, dict):
            # error occurred
            return speaker

        self.update_speaker_fields(speaker=speaker, data=data)
        notify(ObjectCreatedEvent(speaker))
        speaker = add(container, speaker, rename=False)
        return speaker
Exemplo n.º 2
0
    def create_or_modify_content(self, tus_upload):
        metadata = tus_upload.metadata()
        filename = metadata.get("filename", "")
        content_type = metadata.get("content-type", "application/octet-stream")
        mode = metadata.get("mode", "create")
        fieldname = metadata.get("fieldname")

        if mode == "create":
            type_ = metadata.get("@type")
            if type_ is None:
                ctr = getToolByName(self.context, "content_type_registry")
                type_ = ctr.findTypeName(filename.lower(), content_type,
                                         "") or "File"

            obj = create(self.context, type_)
        else:
            obj = self.context

        if not fieldname:
            info = IPrimaryFieldInfo(obj, None)
            if info is not None:
                fieldname = info.fieldname
            elif base_hasattr(obj, "getPrimaryField"):
                field = obj.getPrimaryField()
                fieldname = field.getName()

        if not fieldname:
            return self.error("Bad Request", "Fieldname required", 400)

        # Acquisition wrap temporarily for deserialization
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"):
            obj = obj.__of__(self.context)
            temporarily_wrapped = True

        # Update field with file data
        deserializer = queryMultiAdapter((obj, self.request),
                                         IDeserializeFromJson)
        if deserializer is None:
            return self.error(
                "Not Implemented",
                f"Cannot deserialize type {obj.portal_type}",
                501,
            )
        try:
            deserializer(data={fieldname: tus_upload}, create=mode == "create")
        except DeserializationError as e:
            return self.error("Deserialization Error", str(e), 400)

        if temporarily_wrapped:
            obj = aq_base(obj)

        if mode == "create":
            if not getattr(deserializer, "notifies_create", False):
                notify(ObjectCreatedEvent(obj))
            obj = add(self.context, obj)

        tus_upload.close()
        tus_upload.cleanup()
        self.request.response.setHeader("Location", obj.absolute_url())
Exemplo n.º 3
0
    def setUp(self):
        self.portal = self.layer['portal']
        self.request = self.layer['request']

        self.folder = self.portal[self.portal.invokeFactory('Folder',
                                                            id='folder',
                                                            title='My Folder')]
        self.obj = add(self.folder,
                       create(self.folder, 'Document', title='My Document'))
Exemplo n.º 4
0
    def setUp(self):
        self.portal = self.layer['portal']
        self.request = self.layer['request']
        setRoles(self.portal, TEST_USER_ID, ['Contributor'])

        self.folder = self.portal[self.portal.invokeFactory('Folder',
                                                            id='folder',
                                                            title='My Folder')]
        self.obj = add(self.folder,
                       create(self.folder, 'Document', title='My Document'))
Exemplo n.º 5
0
    def test_add_content_to_container_and_move_on_added_event(self):
        sm = getGlobalSiteManager()

        def move_object(event):
            self.portal.manage_pasteObjects(
                cb_copy_data=self.folder.manage_cutObjects(
                    ids=['my-document']))

        sm.registerHandler(move_object, (IObjectAddedEvent, ))

        obj = add(self.folder, self.obj)
        self.assertEqual(aq_parent(obj), self.portal)

        sm.unregisterHandler(move_object, (IObjectAddedEvent, ))
Exemplo n.º 6
0
    def create_talk(self, data, speaker):
        container = self.talks_container()
        if not container:
            raise Exception('Unable to create a talk proposal. '
                            'Folder "talks" not available.')
        title = data.get('title', None)
        talk = self.create_obj(data=data,
                               type_='Talk',
                               title=title,
                               container=container)
        talk_fields = getFields(ITalk)
        for k, v in data.items():
            if k in talk_fields.keys():
                setattr(talk, k, v)

        # add speaker/talk relation
        intids = getUtility(IIntIds)
        to_id = intids.getId(speaker)
        talk.related_people = [RelationValue(to_id)]
        notify(ObjectCreatedEvent(talk))
        talk = add(container, talk, rename=False)
        return talk
def create_content_from_fhir_json(container, fhir_json):
    """ """
    body = {
        "@type": fhir_json["resourceType"],
        "title": "{0}/{1}".format(fhir_json["resourceType"], fhir_json["id"]),
        "{0}_resource".format(fhir_json["resourceType"].lower()): fhir_json,
    }

    request = TestRequest(BODY=json.dumps(body))
    obj = create(container,
                 body["@type"],
                 id_=fhir_json["id"],
                 title=body["title"])

    deserializer = queryMultiAdapter((obj, request), IDeserializeFromJson)

    notify(ObjectCreatedEvent(obj))

    deserializer(validate_all=True)

    obj = add(container, obj, False)

    return obj
Exemplo n.º 8
0
    def create_or_modify_content(self, tus_upload):
        metadata = tus_upload.metadata()
        filename = metadata.get('filename', '')
        content_type = metadata.get('content-type',
                                    'application/octet-stream')
        mode = metadata.get('mode', 'create')
        fieldname = metadata.get('fieldname')

        if mode == 'create':
            type_ = metadata.get('@type')
            if type_ is None:
                ctr = getToolByName(self.context, 'content_type_registry')
                type_ = ctr.findTypeName(
                    filename.lower(), content_type, '') or 'File'

            obj = create(self.context, type_)
        else:
            obj = self.context

        if not fieldname:
            info = IPrimaryFieldInfo(obj, None)
            if info is not None:
                fieldname = info.fieldname
            elif base_hasattr(obj, 'getPrimaryField'):
                field = obj.getPrimaryField()
                fieldname = field.getName()

        if not fieldname:
            return self.error('Bad Request', 'Fieldname required', 400)

        # Acquisition wrap temporarily for deserialization
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, 'aq_base'):
            obj = obj.__of__(self.context)
            temporarily_wrapped = True

        # Update field with file data
        deserializer = queryMultiAdapter(
            (obj, self.request), IDeserializeFromJson)
        if deserializer is None:
            return self.error(
                'Not Implemented',
                'Cannot deserialize type {}'.format(
                    obj.portal_type),
                501)
        try:
            deserializer(
                data={fieldname: tus_upload}, create=mode == 'create')
        except DeserializationError as e:
            return self.error(
                'Deserialization Error', str(e), 400)

        if temporarily_wrapped:
            obj = aq_base(obj)

        if mode == 'create':
            if not getattr(deserializer, 'notifies_create', False):
                notify(ObjectCreatedEvent(obj))
            obj = add(self.context, obj)

        tus_upload.close()
        tus_upload.cleanup()
        self.request.response.setHeader('Location', obj.absolute_url())
Exemplo n.º 9
0
 def test_add_content_to_container_keeps_id(self):
     obj = create(self.folder, "Document", "doc-1", "My Document")
     obj = add(self.folder, obj, rename=False)
     self.assertEqual(obj.getId(), "doc-1")
Exemplo n.º 10
0
 def test_add_content_to_container_renames_id(self):
     obj = create(self.folder, "Document", title="My Document")
     obj = add(self.folder, obj)
     self.assertEqual(obj.getId(), "my-document")
Exemplo n.º 11
0
 def test_add_content_to_container(self):
     obj = create(self.folder, "Document", "my-document")
     obj = add(self.folder, obj)
     self.assertEqual(aq_parent(obj), self.folder)
Exemplo n.º 12
0
    def reply(self):

        tus_upload = self.tus_upload()
        if tus_upload is None:
            return self.error('Not Found', '', 404)

        metadata = tus_upload.metadata()
        self.check_add_modify_permission(metadata.get('mode', 'create'))

        if not self.check_tus_version():
            return self.unsupported_version()

        content_type = self.request.getHeader('Content-Type')
        if content_type != 'application/offset+octet-stream':
            return self.error('Bad Request',
                              'Missing or invalid Content-Type header')

        offset = self.request.getHeader('Upload-Offset', '')
        try:
            offset = int(offset)
        except ValueError:
            return self.error('Bad Request',
                              'Missing or invalid Upload-Offset header')

        tus_upload.write(self.request._file, offset)

        if tus_upload.finished:
            offset = tus_upload.offset()
            filename = metadata.get('filename', '')
            content_type = metadata.get('content-type',
                                        'application/octet-stream')
            mode = metadata.get('mode', 'create')
            fieldname = metadata.get('fieldname')

            if mode == 'create':
                type_ = metadata.get('@type')
                if type_ is None:
                    ctr = getToolByName(self.context, 'content_type_registry')
                    type_ = ctr.findTypeName(filename.lower(), content_type,
                                             '') or 'File'

                obj = create(self.context, type_)
                notify(ObjectCreatedEvent(obj))
                obj = add(self.context, obj)
            else:
                obj = self.context

            if not fieldname:
                info = IPrimaryFieldInfo(obj, None)
                if info is not None:
                    fieldname = info.fieldname
                elif base_hasattr(obj, 'getPrimaryField'):
                    field = obj.getPrimaryField()
                    fieldname = field.getName()

            if not fieldname:
                return self.error('Bad Request', 'Fieldname required', 400)

            # Update field with file data
            deserializer = queryMultiAdapter((obj, self.request),
                                             IDeserializeFromJson)
            if deserializer is None:
                return self.error(
                    'Not Implemented',
                    'Cannot deserialize type {}'.format(obj.portal_type), 501)
            try:
                deserializer(data={fieldname: tus_upload})
            except DeserializationError as e:
                return self.error('Deserialization Error', str(e), 400)

            if mode == 'create':
                rename(obj)

            tus_upload.close()
            tus_upload.cleanup()
            self.request.response.setHeader('Location', obj.absolute_url())
        else:
            offset = tus_upload.offset()
            self.request.response.setHeader('Upload-Expires',
                                            tus_upload.expires())

        self.request.response.setHeader('Tus-Resumable', '1.0.0')
        self.request.response.setHeader('Upload-Offset', '{}'.format(offset))
        self.request.response.setStatus(204, lock=1)
        return super(UploadPatch, self).reply()
Exemplo n.º 13
0
 def test_add_content_to_container(self):
     obj = add(self.folder, self.obj)
     self.assertEqual(aq_parent(obj), self.folder)
Exemplo n.º 14
0
    def import_item(self, dirpath, *filenames):
        __traceback_info__ = dirpath
        logger.info("Importing item at %s", dirpath)
        all_info = {}
        blobs = {}
        for name in filenames:
            filepath = os.path.join(dirpath, name)
            key, ext = os.path.splitext(name)
            if ext != ".json":
                logger.info("Found non json file, will use as blob, at %s",
                            filepath)
                blobs[key] = filepath
                continue
            logger.info("Reading %s", filepath)
            with open(filepath) as myfile:
                content = json.loads(myfile.read())
            all_info[key] = content

        # Get meta info.  We might also get some of this from default.json.
        # Maybe we need less in meta.
        meta = all_info["meta"]
        # if "front-page" in meta.get("path", ""):
        #     import pdb; pdb.set_trace()
        # See if the object already exists.
        obj = self.get_object(**meta)
        if obj is None:
            # We need to get some parent, either from default["parent"] or meta.
            path = meta["path"]
            parent_path = path.rpartition("/")[0]
            parent_obj = self.get_object(path=parent_path)
            if parent_obj is None:
                logger.warning(
                    "Parent object not found, cannot create content for %s",
                    path)
                return
            default = all_info["default"]
            # Code taken from plone.restapi add.py FolderPost.reply.
            # It would be nice if we could call that method directly, but it does too much.
            # We would need to split it a bit, especially:
            # don't get json from the request body, and don't change the response.
            type_ = default.get("@type", None)
            id_ = default.get("id", None)
            title = default.get("title", None)
            translation_of = default.get("translation_of", None)
            language = default.get("language", None)
            # except Unauthorized / BadRequest
            obj = create(parent_obj, type_, id_=id_, title=title)
            # Acquisition wrap temporarily to satisfy things like vocabularies
            # depending on tools
            temporarily_wrapped = False
            if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"):
                obj = obj.__of__(self.context)
                temporarily_wrapped = True
            deserializer = queryMultiAdapter((obj, self.request),
                                             IDeserializeFromJson)
            if deserializer is None:
                logger.error("Cannot deserialize type %s", obj.portal_type)
                return
            if blobs:
                for fieldname, path in blobs.items():
                    if fieldname in default:
                        with open(path, "rb") as myfile:
                            default[fieldname]["data"] = myfile.read()

            # except DeserializationError as e:
            deserializer(validate_all=True, data=default, create=True)
            if temporarily_wrapped:
                obj = aq_base(obj)
            if not getattr(deserializer, "notifies_create", False):
                notify(ObjectCreatedEvent(obj))
            obj = add(parent_obj, obj, rename=not bool(id_))
            obj_path = "/".join(obj.getPhysicalPath())
            logger.info("Created %s at %s", type_, obj_path)

            # Link translation given the translation_of property
            if PAM_INSTALLED:
                # Note: untested.
                from plone.app.multilingual.interfaces import (
                    IPloneAppMultilingualInstalled, )  # noqa
                from plone.app.multilingual.interfaces import ITranslationManager

                if (IPloneAppMultilingualInstalled.providedBy(self.request)
                        and translation_of and language):
                    source = self.get_object(translation_of)
                    if source:
                        manager = ITranslationManager(source)
                        manager.register_translation(language, obj)

            # TODO: call other, named deserializers, but they do not work currently anyway.
        else:
            obj_path = "/".join(obj.getPhysicalPath())
            if is_locked(obj, self.request):
                # TODO: We could throw an error, but we should probably just unlock.
                logger.warning("Content is locked: %s", obj_path)
            logger.info("Updating existing content at %s", obj_path)
            deserializers = getAdapters((obj, self.request),
                                        IDeserializeFromJson)
            if not deserializers:
                logger.error("Cannot deserialize type %s", obj.portal_type)
                return
            for name, deserializer in deserializers:
                if not name:
                    name = "default"
                # XXX This traceback info overrides the previous.
                # When done in a separate method, it should be fine.
                # __traceback_info__ = name
                __traceback_info__ = dirpath, name
                content = all_info[name]
                if name == "local_roles":
                    # TODO Fix this in plone.restapi.
                    logger.info(
                        "Ignoring local_roles deserializer for now, as it does not accept a content parameter."
                    )
                    continue
                if name == "default" and blobs:
                    for fieldname, path in blobs.items():
                        if fieldname in content:
                            with open(path, "rb") as myfile:
                                content[fieldname]["data"] = myfile.read()
                try:
                    deserializer(data=content)
                except TypeError:
                    # Happens for site root.  But I want to fix it there too, if that is acceptable.
                    logger.info(
                        "TypeError, likely because deserializer does not accept data keyword argument: %s",
                        deserializer)
            # TODO: maybe try / except DeserializationError

        # Report back that we made an import.
        return True
Exemplo n.º 15
0
 def add_object_to_context(self):
     self.obj = add(self.context, self.obj, rename=not bool(self.id_))
def create_item_runner(
        container,
        content_structure,
        auto_id=False,
        default_lang=None,
        default_wf_action=None,
        ignore_wf_types=['Image', 'File'],
        logger=logger):
    """Create Dexterity contents from plone.restapi compatible structures.

    :param container: The context in which the item should be created.
    :type container: Plone content object
    :param content_structure: Python dictionary with content structure.
    :type content_structure: dict
    :param default_lang: Default language.
    :type default_lang: string
    :param default_wf_action: Default workflow transition action.
    :type default_wf_action: string
    :param ignore_wf_types: Ignore to apply the workflow transition if item is
                            one of these types.
    :type ignore_wf_types: list (default: ['Image', 'File'])
    :param logger: Logger to use.
    :type logger: Python logging instance.

    The datastructure of content defined by plone.restapi:

    https://plonerestapi.readthedocs.io/en/latest/content.html#creating-a-resource-with-post

    [
        {
            "type": "",
            "id": "",
            "title": "",
            "description": ""
            "items": [],
            "opts": {
                "default_page": "",
                "locally_allowed_types": [],
                "immediately_allowed_types": [],
            }
        }
    ]

    Use the same structure for each child. Leave out, what you don't need.
    """

    request = getRequest()

    for data in content_structure:

        type_ = data.get('@type', None)
        id_ = data.get('id', None)
        title = data.get('title', None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        obj = create(container, type_, id_=id_, title=title)

        # Acquisition wrap temporarily to satisfy things like vocabularies
        # depending on tools
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, 'aq_base'):
            obj = obj.__of__(container)
            temporarily_wrapped = True

        deserializer = queryMultiAdapter((obj, request), IDeserializeFromJson)

        if deserializer is None:
            raise BadRequest(
                'Canno deserialize type {}'.format(obj.portal_type))

        # defaults
        if not data.get('language'):
            data['language'] = default_lang

        if not data.get('review_state'):
            data['review_state'] = default_wf_action

        deserializer(validate_all=True, data=data, create=True)

        if temporarily_wrapped:
            obj = aq_base(obj)

        if not getattr(deserializer, 'notifies_create', False):
            notify(ObjectCreatedEvent(obj))

        obj = add(container, obj, rename=not bool(id_))

        # set default
        opts = data.get('opts', {})
        if opts.get('default_page', False):
            container.setDefaultPage(obj.id)

        # CONSTRAIN TYPES
        locally_allowed_types = opts.get('locally_allowed_types', False)
        immediately_allowed_types = opts.get('immediately_allowed_types', False)
        if locally_allowed_types or immediately_allowed_types:
            be = ISelectableConstrainTypes(obj, None)
            if be:
                be.setConstrainTypesMode(behaviors.constrains.ENABLED)
                if locally_allowed_types:
                    be.setLocallyAllowedTypes = locally_allowed_types
                    logger.debug('{0}: locally_allowed_types {1}'.format(path, locally_allowed_types))  # noqa
                if immediately_allowed_types:
                    be.setImmediatelyAddableTypes = immediately_allowed_types
                    logger.debug('{0}: immediately_allowed_types {1}'.format(path, immediately_allowed_types))  # noqa

        id_ = obj.id  # get the real id
        path = '/'.join(obj.getPhysicalPath())
        logger.info('{0}: created'.format(path))

        # Call recursively
        create_item_runner(
            obj,
            content_structure=data.get('items', []),
            default_lang=default_lang,
            default_wf_action=default_wf_action,
            logger=logger,
        )
Exemplo n.º 17
0
    def do_reply(self):
        """This is the reply method from plone.restapi, overrided
           to manage returning the fullobject after creation or the summary."""

        # imio.restapi, nothing changed until next comment "imio.restapi ..." comment
        data = json_body(self.request)

        type_ = data.get("@type", None)
        id_ = data.get("id", None)
        title = data.get("title", None)
        translation_of = data.get("translation_of", None)
        language = data.get("language", None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request, plone.protect.interfaces.IDisableCSRFProtection)

        try:
            obj = create(self.context, type_, id_=id_, title=title)
        except Unauthorized as exc:
            self.request.response.setStatus(403)
            return dict(error=dict(type="Forbidden", message=str(exc)))
        except BadRequest as exc:
            self.request.response.setStatus(400)
            return dict(error=dict(type="Bad Request", message=str(exc)))

        # Acquisition wrap temporarily to satisfy things like vocabularies
        # depending on tools
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"):
            obj = obj.__of__(self.context)
            temporarily_wrapped = True

        # Update fields
        deserializer = queryMultiAdapter((obj, self.request), IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(
                error=dict(message="Cannot deserialize type {}".format(obj.portal_type))
            )

        try:
            deserializer(validate_all=True, create=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(type="DeserializationError", message=str(e)))

        if temporarily_wrapped:
            obj = aq_base(obj)

        if not getattr(deserializer, "notifies_create", False):
            notify(ObjectCreatedEvent(obj))

        obj = add(self.context, obj, rename=not bool(id_))

        # Link translation given the translation_of property
        if PAM_INSTALLED and PLONE5:
            from plone.app.multilingual.interfaces import (
                IPloneAppMultilingualInstalled,
            )  # noqa
            from plone.app.multilingual.interfaces import ITranslationManager

            if (
                IPloneAppMultilingualInstalled.providedBy(self.request)
                and translation_of
                and language
            ):
                source = self.get_object(translation_of)
                if source:
                    manager = ITranslationManager(source)
                    manager.register_translation(language, obj)

        self.request.response.setStatus(201)
        self.request.response.setHeader("Location", obj.absolute_url())

        # imio.restapi, begin changes, manage returning full object or summary
        return_full_object = data.get(
            "return_fullobject", get_return_fullobject_after_creation_default())
        if return_full_object:
            serializer = queryMultiAdapter((obj, self.request), ISerializeToJson)
        else:
            serializer = queryMultiAdapter((obj, self.request), ISerializeToJsonSummary)

        serialized_obj = serializer()
        # imio.restapi, end changes, manage returning full object or summary

        # HypermediaBatch can't determine the correct canonical URL for
        # objects that have just been created via POST - so we make sure
        # to set it here
        serialized_obj["@id"] = obj.absolute_url()

        return serialized_obj
 def test_add_content_to_container_keeps_id(self):
     obj = create(self.folder, 'Document', 'doc-1', 'My Document')
     obj = add(self.folder, obj, rename=False)
     self.assertEqual(obj.getId(), 'doc-1')
Exemplo n.º 19
0
    def reply(self):
        data = json_body(self.request)

        type_ = data.get('@type', None)
        id_ = data.get('id', None)
        title = data.get('title', None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if 'IDisableCSRFProtection' in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        try:
            obj = create(self.context, type_, id_=id_, title=title)
        except Unauthorized as exc:
            self.request.response.setStatus(403)
            return dict(error=dict(type='Forbidden', message=exc.message))
        except BadRequest as exc:
            self.request.response.setStatus(400)
            return dict(error=dict(type='Bad Request', message=exc.message))

        # Acquisition wrap temporarily to satisfy things like vocabularies
        # depending on tools
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, 'aq_base'):
            obj = obj.__of__(self.context)
            temporarily_wrapped = True

        # Update fields
        deserializer = queryMultiAdapter((obj, self.request),
                                         IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(error=dict(
                message='Cannot deserialize type {}'.format(obj.portal_type)))

        try:
            deserializer(validate_all=True, create=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(
                error=dict(type='DeserializationError', message=str(e)))

        if temporarily_wrapped:
            obj = aq_base(obj)

        if not getattr(deserializer, 'notifies_create', False):
            notify(ObjectCreatedEvent(obj))

        obj = add(self.context, obj, rename=not bool(id_))

        self.request.response.setStatus(201)
        self.request.response.setHeader('Location', obj.absolute_url())

        serializer = queryMultiAdapter((obj, self.request), ISerializeToJson)

        serialized_obj = serializer()

        # HypermediaBatch can't determine the correct canonical URL for
        # objects that have just been created via POST - so we make sure
        # to set it here
        serialized_obj['@id'] = obj.absolute_url()

        return serialized_obj
Exemplo n.º 20
0
    def reply(self):
        data = json_body(self.request)

        type_ = data.get("@type", None)
        id_ = data.get("id", None)
        title = data.get("title", None)
        translation_of = data.get("translation_of", None)
        language = data.get("language", None)
        uid = data.get("UID", None)

        if not type_:
            raise BadRequest("Property '@type' is required")

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        sm = getSecurityManager()
        # ManagePortal is required to set the uid of an object during creation
        if uid and not sm.checkPermission(ManagePortal, self.context):
            self.request.response.setStatus(403)
            msg = "Setting UID of an object requires Manage Portal permission"
            return dict(error=dict(type="Forbidden", message=msg))

        try:
            obj = create(self.context, type_, id_=id_, title=title)
        except Unauthorized as exc:
            self.request.response.setStatus(403)
            return dict(error=dict(type="Forbidden", message=str(exc)))
        except BadRequest as exc:
            self.request.response.setStatus(400)
            return dict(error=dict(type="Bad Request", message=str(exc)))

        # Acquisition wrap temporarily to satisfy things like vocabularies
        # depending on tools
        temporarily_wrapped = False
        if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"):
            obj = obj.__of__(self.context)
            temporarily_wrapped = True

        # Update fields
        deserializer = queryMultiAdapter((obj, self.request),
                                         IDeserializeFromJson)
        if deserializer is None:
            self.request.response.setStatus(501)
            return dict(error=dict(
                message=f"Cannot deserialize type {obj.portal_type}"))

        try:
            deserializer(validate_all=True, create=True)
        except DeserializationError as e:
            self.request.response.setStatus(400)
            return dict(
                error=dict(type="DeserializationError", message=str(e)))

        if temporarily_wrapped:
            obj = aq_base(obj)

        if uid:
            setattr(obj, "_plone.uuid", uid)

        if not getattr(deserializer, "notifies_create", False):
            notify(ObjectCreatedEvent(obj))

        obj = add(self.context, obj, rename=not bool(id_))

        # Link translation given the translation_of property
        if (IPloneAppMultilingualInstalled.providedBy(self.request)
                and translation_of and language):
            source = self.get_object(translation_of)
            if source:
                manager = ITranslationManager(source)
                manager.register_translation(language, obj)

        self.request.response.setStatus(201)
        self.request.response.setHeader("Location", obj.absolute_url())

        serializer = queryMultiAdapter((obj, self.request), ISerializeToJson)

        serialized_obj = serializer()

        # HypermediaBatch can't determine the correct canonical URL for
        # objects that have just been created via POST - so we make sure
        # to set it here
        serialized_obj["@id"] = obj.absolute_url()

        return serialized_obj