Exemplo n.º 1
0
    def destination(self):
        """Return the destination for scanned documents."""
        destination = self.request.form.get('destination', 'inbox')

        if destination == 'inbox':
            inbox = self.find_inbox()
            if api.user.has_permission('opengever.inbox: Scan In', obj=inbox):
                return inbox
            return self.error(
                status=403,
                type_='Forbidden',
                message='The user does not have the required permissions to perform a scan-in via the API.',
                )

        elif destination == 'private':
            # Try to find a dossier with title 'Scaneingang'
            mtool = api.portal.get_tool(name='portal_membership')
            private_folder = mtool.getHomeFolder()
            if private_folder:
                catalog = api.portal.get_tool(name='portal_catalog')
                dossiers = catalog(
                    portal_type='opengever.private.dossier',
                    path={'query': '/'.join(private_folder.getPhysicalPath()),
                          'depth': -1},
                    sortable_title='scaneingang',  # Exact match
                )
                if dossiers:
                    return dossiers[0].getObject()

                # No dossier found, create a new one
                obj = create(
                    private_folder,
                    'opengever.private.dossier',
                    title='Scaneingang')
                rename(obj)
                return obj

        return self.error(
            status=404,
            type_='NotFound',
            message='The scan-in destination does not exist.',
            )
Exemplo n.º 2
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.º 3
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.º 4
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')

        request_body = self.request._file
        if hasattr(request_body, 'raw'):  # Unwrap io.BufferedRandom
            request_body = request_body.raw
        tus_upload.write(request_body, 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_)
            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':
                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())
        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.º 5
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=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_))

        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.º 6
0
    def reply(self):
        data = json_body(self.request)

        type_ = data.get('@type', 'SchemaFormData')
        id_ = data.get('id', None)
        title = data.get(
            'title',
            'Data at %s' % datetime.datetime.now().strftime('%Y-%m-%d %H%M%S'))
        # import pdb;pdb.set_trace()
        schema_form_data = data.get('schema_form_data', {})

        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)

        obj = create(self.context, type_, id_=id_, title=title)

        if isinstance(obj, dict) and 'error' in obj:
            self.request.response.setStatus(400)
            return obj
        obj.schema_form_data = schema_form_data
        # 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)
        # except DeserializationError as e:
        #    self.request.response.setStatus(400)
        #    return dict(error=dict(
        #        type='DeserializationError',
        #        message=str(e)))

        # Rename if generated id
        if not id_:
            rename(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()
        success = {'message': 'successfully added data'}
        return success
Exemplo n.º 7
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