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.', )
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)
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
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()
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
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
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