Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def replace(self, resource, id_, document, original):
model, filter_, fields_, _ = self._datasource_ex(resource, [])
id_field = self._id_field(resource)
filter_ = self.combine_queries(
filter_, parse_dictionary({id_field: id_}, model))
query = self.driver.session.query(model)
# Find and delete the old object
old_model_instance = query.filter(*filter_).first()
if old_model_instance is None:
abort(500, description=debug_error_message('Object not existent'))
self._handle_immutable_id(id_field, old_model_instance, document)
self.driver.session.delete(old_model_instance)
# create and insert the new one
model_instance = self._create_model_instance(resource, document)
id_field = self._id_field(resource)
setattr(model_instance, id_field, id_)
self.driver.session.add(model_instance)
self.driver.session.commit()
description=debug_error_message(
"pymongo.errors.DuplicateKeyError: %s" % e
),
)
except (pymongo.errors.WriteError, pymongo.errors.OperationFailure) as e:
# server error codes and messages changed between 2.4 and 2.6/3.0.
server_version = self.driver.db.client.server_info()["version"][:3]
if (server_version == "2.4" and e.code in (13596, 10148)) or e.code in (
66,
16837,
):
# attempt to update an immutable field. this usually
# happens when a PATCH or PUT includes a mismatching ID_FIELD.
self.app.logger.warning(e)
description = (
debug_error_message("pymongo.errors.OperationFailure: %s" % e)
or "Attempt to update an immutable field. Usually happens "
"when PATCH or PUT include a '%s' field, "
"which is immutable (PUT can include it as long as "
"it is unchanged)." % id_field
)
abort(400, description=description)
else:
# see comment in :func:`insert()`.
self.app.logger.exception(e)
abort(
500,
description=debug_error_message(
"pymongo.errors.OperationFailure: %s" % e
),
result = (
coll.replace_one(filter_, changes)
if replace
else coll.update_one(filter_, changes)
)
if (
config.ETAG in original
and result
and result.acknowledged
and result.modified_count == 0
):
raise self.OriginalChangedError()
except pymongo.errors.DuplicateKeyError as e:
abort(
400,
description=debug_error_message(
"pymongo.errors.DuplicateKeyError: %s" % e
),
)
except (pymongo.errors.WriteError, pymongo.errors.OperationFailure) as e:
# server error codes and messages changed between 2.4 and 2.6/3.0.
server_version = self.driver.db.client.server_info()["version"][:3]
if (server_version == "2.4" and e.code in (13596, 10148)) or e.code in (
66,
16837,
):
# attempt to update an immutable field. this usually
# happens when a PATCH or PUT includes a mismatching ID_FIELD.
self.app.logger.warning(e)
description = (
debug_error_message("pymongo.errors.OperationFailure: %s" % e)
or "Attempt to update an immutable field. Usually happens "
def sanitize_keys(spec):
ops = set([op for op in spec.keys() if op[0] == '$'])
unknown = ops - Mongo.operators
if unknown:
abort(400, description=debug_error_message(
'Query contains unknown or unsupported operators: %s' %
', '.join(unknown)
))
if set(spec.keys()) & set(config.MONGO_QUERY_BLACKLIST):
abort(400, description=debug_error_message(
'Query contains operators banned in MONGO_QUERY_BLACKLIST'
))
try:
client_sort = ast.literal_eval(req.sort)
except Exception as e:
abort(400, description=debug_error_message(str(e)))
if req.where:
try:
spec = self._sanitize(json.loads(req.where))
except HTTPException as e:
# _sanitize() is raising an HTTP exception; let it fire.
raise
except:
try:
spec = parse(req.where)
except ParseError:
abort(400, description=debug_error_message(
'Unable to parse `where` clause'
))
if sub_resource_lookup:
spec.update(sub_resource_lookup)
spec = self._mongotize(spec, resource)
bad_filter = validate_filters(spec, resource)
if bad_filter:
abort(400, bad_filter)
client_projection = self._client_projection(req)
datasource, spec, projection, sort = self._datasource_ex(
resource,
build_response_document(updated, resource, embedded_fields, updated)
response = updated
if config.IF_MATCH:
etag = response[config.ETAG]
else:
issues = validator.errors
except DocumentError as e:
# TODO should probably log the error and abort 400 instead (when we
# got logging)
issues["validator exception"] = str(e)
except exceptions.HTTPException as e:
raise e
except Exception as e:
# consider all other exceptions as Bad Requests
app.logger.exception(e)
abort(400, description=debug_error_message("An exception occurred: %s" % e))
if len(issues):
response[config.ISSUES] = issues
response[config.STATUS] = config.STATUS_ERR
status = config.VALIDATION_ERROR_STATUS
else:
response[config.STATUS] = config.STATUS_OK
status = 200
# limit what actually gets sent to minimize bandwidth usage
response = marshal_write_response(response, resource)
return response, last_modified, etag, status
build_response_document(document, resource, embedded_fields, document)
response = document
if config.IF_MATCH:
etag = response[config.ETAG]
else:
issues = validator.errors
except DocumentError as e:
# TODO should probably log the error and abort 400 instead (when we
# got logging)
issues["validator exception"] = str(e)
except exceptions.HTTPException as e:
raise e
except Exception as e:
# consider all other exceptions as Bad Requests
app.logger.exception(e)
abort(400, description=debug_error_message("An exception occurred: %s" % e))
if issues:
response[config.ISSUES] = issues
response[config.STATUS] = config.STATUS_ERR
status = config.VALIDATION_ERROR_STATUS
else:
response[config.STATUS] = config.STATUS_OK
status = 200
# limit what actually gets sent to minimize bandwidth usage
response = marshal_write_response(response, resource)
return response, last_modified, etag, status
req = parse_request(resource)
embedded_fields = resolve_embedded_fields(resource, req)
# validation, and additional fields
if payl is None:
payl = payload()
if isinstance(payl, dict):
payl = [payl]
if not payl:
# empty bulk insert
abort(400, description=debug_error_message("Empty bulk insert"))
if len(payl) > 1 and not config.DOMAIN[resource]["bulk_enabled"]:
abort(400, description=debug_error_message("Bulk insert not allowed"))
for value in payl:
document = []
doc_issues = {}
try:
document = parse(value, resource)
resolve_sub_resource_path(document, resource)
if skip_validation:
validation = True
else:
validation = validator.validate(document)
if validation: # validation is successful
# validator might be not available if skip_validation. #726.
if validator:
# Apply coerced values
document = validator.document
doc.update(dict(model.to_mongo()))
doc[config.ID_FIELD] = model.id
clean_doc(doc)
return ids
else:
model = self._doc_to_model(resource, doc_or_docs)
model.save(write_concern=self._wc(resource))
doc_or_docs.update(dict(model.to_mongo()))
doc_or_docs[config.ID_FIELD] = model.id
clean_doc(doc_or_docs)
return model.id
except pymongo.errors.OperationFailure as e:
# most likely a 'w' (write_concern) setting which needs an
# existing ReplicaSet which doesn't exist. Please note that the
# update will actually succeed (a new ETag will be needed).
abort(500, description=debug_error_message(
'pymongo.errors.OperationFailure: %s' % e
))
except Exception as exc:
self._handle_exception(exc)
else:
ret_file = None
if config.EXTENDED_MEDIA_INFO:
ret = {"file": ret_file}
# check if we should return any special fields
for attribute in config.EXTENDED_MEDIA_INFO:
if hasattr(_file, attribute):
# add extended field if found in the file object
ret.update({attribute: getattr(_file, attribute)})
else:
# tried to select an invalid attribute
abort(
500,
description=debug_error_message(
"Invalid extended media attribute requested"
),
)
return ret
else:
return ret_file
else:
return None