def get_keyword_query(self, **kw): """Generates a query from the given keywords. Only known indexes make it into the generated query. :returns: Catalog query :rtype: dict """ query = dict() # Only known indexes get observed indexes = self.catalog.get_indexes() # Handle additional keyword parameters for k, v in kw.iteritems(): # handle uid in keywords if k.lower() == "uid": k = "UID" # handle portal_type in keywords if k.lower() == "portal_type": if v: v = _.to_list(v) if k not in indexes: logger.warn("Skipping unknown keyword parameter '%s=%s'" % (k, v)) continue if v is None: logger.warn("Skip None value in kw parameter '%s=%s'" % (k, v)) continue logger.debug("Adding '%s=%s' to query" % (k, v)) query[k] = v return query
def _set(self, instance, value, **kw): """Set the value of the field """ logger.debug("DexterityFieldManager::set: value=%r" % value) # Check if the field is read only if self.field.readonly: raise Unauthorized("Field is read only") fieldname = self.get_field_name() # id fields take only strings if fieldname == "id": value = str(value) try: # Validate self.field.validate(value) # TODO: Check security on the field level return self.field.set(instance, value) except WrongType: logger.warn("WrongType: Field={} Value={}".format( self.field, value)) except: # noqa logger.warn("Unknown Exception: Field={} Value={}".format( self.field, value))
def _set(self, instance, value, **kw): """Set the value of the field """ logger.debug("ATFieldManager::set: value=%r" % value) # check field permission if not self.field.checkPermission("write", instance): raise Unauthorized( "You are not allowed to write the field {}".format(self.name)) # check if field is writable if not self.field.writeable(instance): raise Unauthorized("Field {} is read only.".format(self.name)) # id fields take only strings if self.name == "id": value = str(value) # get the field mutator mutator = self.field.getMutator(instance) # Inspect function and apply *args and **kwargs if possible. mapply(mutator, value, **kw) return True
def extract_fields(self): """Extract the given fieldnames from the object :returns: Schema name/value mapping :rtype: dict """ # get the proper data manager for the object dm = IDataManager(self.context) # filter out ignored fields fieldnames = filter(lambda name: name not in self.ignore, self.keys) # schema mapping out = dict() for fieldname in fieldnames: try: # get the field value with the data manager fieldvalue = dm.json_data(fieldname) # https://github.com/collective/plone.jsonapi.routes/issues/52 # -> skip restricted fields except Unauthorized: logger.debug("Skipping restricted field '%s'" % fieldname) continue except ValueError: logger.debug("Skipping invalid field '%s'" % fieldname) continue out[fieldname] = api.to_json_value(self.context, fieldname, fieldvalue) return out
def _get(self, instance, **kw): """Get the value of the field """ logger.debug("DexterityFieldManager::get: instance={} field={}".format( instance, self.field)) # TODO: Check security on the field level return self.field.get(instance)
def get_index(self, name): """get an index by name TODO: Combine indexes of relevant catalogs depending on the portal_type which is searched for. """ catalog = self.get_catalog() index = catalog._catalog.getIndex(name) logger.debug("get_index={} of catalog '{}' --> {}".format( name, catalog.__name__, index)) return index
def set(self, instance, value, **kw): """Decodes base64 value and set the file object """ value = str(value).decode("base64") # handle the filename if "filename" not in kw: logger.debug("FielFieldManager::set: No Filename detected " "-> using title or id") kw["filename"] = kw.get("id") or kw.get("title") self._set(instance, value, **kw)
def _get(self, instance, **kw): """Get the value of the field """ logger.debug("ATFieldManager::get: instance={} field={}".format( instance, self.field)) # check the field permission if not self.field.checkPermission("read", instance): raise Unauthorized( "You are not allowed to read the field {}".format(self.name)) # return the field value return self.field.get(instance)
def update_object_with_data(content, record): """Update the content with the record data :param content: A single folderish catalog brain or content object :type content: ATContentType/DexterityContentType/CatalogBrain :param record: The data to update :type record: dict :returns: The updated content object :rtype: object :raises: APIError, :class:`~plone.jsonapi.routes.exceptions.APIError` """ # ensure we have a full content object content = get_object(content) # Look for an update-specific adapter for this object adapter = queryAdapter(content, IUpdate) if adapter: # Use the adapter to update the object logger.info("Delegating 'update' operation of '{}'".format( api.get_path(content))) adapter.update_object(**record) else: # Fall-back to default update machinery # get the proper data manager dm = IDataManager(content) if dm is None: fail(400, "Update for this object is not allowed") # Bail-out non-update-able fields purged_records = copy.deepcopy(record) map(lambda key: purged_records.pop(key, None), SKIP_UPDATE_FIELDS) # Iterate through record items for k, v in purged_records.items(): try: success = dm.set(k, v, **record) except Unauthorized: fail(401, "Not allowed to set the field '%s'" % k) except ValueError, exc: fail(400, str(exc)) if not success: logger.warn("update_object_with_data::skipping key=%r", k) continue logger.debug("update_object_with_data::field %r updated", k)
def _set(self, instance, value, **kw): """Set the value of the field """ logger.debug("DexterityFieldManager::set: value=%r" % value) # Check if the field is read only if self.field.readonly: raise Unauthorized("Field is read only") # Validate self.field.validate(value) # TODO: Check security on the field level return self.field.set(instance, value)
def set(self, instance, value, **kw): logger.debug( "NamedFileFieldManager::set:File field" "detected ('%r'), base64 decoding value", self.field) data = str(value).decode("base64") filename = kw.get("filename") or kw.get("id") or kw.get("title") contentType = kw.get("mimetype") or kw.get("content_type") if contentType: # create NamedFile with content type information value = self.field._type(data=data, contentType=contentType, filename=filename) else: # create NamedFile w/o content type information # -> will be guessed by the extension of the filename value = self.field._type(data=data, filename=filename) return self.field.set(instance, value)
def update_object_with_data(content, record): """Update the content with the record data :param content: A single folderish catalog brain or content object :type content: ATContentType/DexterityContentType/CatalogBrain :param record: The data to update :type record: dict :returns: The updated content object :rtype: object :raises: APIError, :class:`~plone.jsonapi.routes.exceptions.APIError` """ # ensure we have a full content object content = get_object(content) # get the proper data manager dm = IDataManager(content) if dm is None: fail(400, "Update for this object is not allowed") # Iterate through record items for k, v in record.items(): try: success = dm.set(k, v, **record) except Unauthorized: fail(401, "Not allowed to set the field '%s'" % k) except ValueError, exc: fail(400, str(exc)) if not success: logger.warn("update_object_with_data::skipping key=%r", k) continue logger.debug("update_object_with_data::field %r updated", k)
if not success: logger.warn("update_object_with_data::skipping key=%r", k) continue logger.debug("update_object_with_data::field %r updated", k) # Validate the entire content object invalid = validate_object(content, record) if invalid: fail(400, u.to_json(invalid)) # do a wf transition if record.get("transition", None): t = record.get("transition") logger.debug(">>> Do Transition '%s' for Object %s", t, content.getId()) do_transition_for(content, t) # reindex the object content.reindexObject() return content def validate_object(brain_or_object, data): """Validate the entire object :param brain_or_object: A single catalog brain or content object :type brain_or_object: ATContentType/DexterityContentType/CatalogBrain :param data: The sharing dictionary as returned from the API :type data: dict :returns: invalidity status