def patch_record(record, request): # XXX: add util clone_request() backup_pattern = request.matched_route.pattern backup_body = request.body backup_validated = request.validated # Instantiate record resource with current request. context = RouteFactory(request) context.resource_name = 'record' context.get_permission_object_id = lambda r, i: record_uri(r) record_pattern = request.matched_route.pattern.replace('/attachment', '') request.matched_route.pattern = record_pattern # Simulate update of fields. request.validated = dict(body=record, **backup_validated) request.body = json.dumps(record).encode('utf-8') resource = Record(request, context=context) setattr(request, '_attachment_auto_save', True) # Flag in update listener. try: saved = resource.patch() except httpexceptions.HTTPNotFound: saved = resource.put() request.matched_route.pattern = backup_pattern request.body = backup_body request.validated = backup_validated return saved
def resource_create_object(request, resource_cls, uri): """Implicitly create a resource (or fail silently). In the default bucket, the bucket and collection are implicitly created. This helper creates one of those resources using a simulated request and context that is appropriate for the resource. Also runs create events as though the resource were created in a subrequest. If the resource already exists, do nothing. """ resource_name, matchdict = view_lookup(request, uri) # Build a fake request, mainly used to populate the create events that # will be triggered by the resource. fakerequest = build_request(request, { 'method': 'PUT', 'path': uri, }) fakerequest.matchdict = matchdict fakerequest.bound_data = request.bound_data fakerequest.authn_type = request.authn_type fakerequest.selected_userid = request.selected_userid fakerequest.errors = request.errors fakerequest.current_resource_name = resource_name obj_id = matchdict['id'] # Fake context, required to instantiate a resource. context = RouteFactory(fakerequest) context.resource_name = resource_name resource = resource_cls(fakerequest, context) # Check that provided id is valid for this resource. if not resource.model.id_generator.match(obj_id): error_details = { 'location': 'path', 'description': 'Invalid {} id'.format(resource_name) } raise_invalid(resource.request, **error_details) data = {'id': obj_id} try: obj = resource.model.create_record(data) except UnicityError as e: # The record already exists; skip running events return e.record # Since the current request is not a resource (but a straight Service), # we simulate a request on a resource. # This will be used in the resource event payload. resource.postprocess(obj, action=ACTIONS.CREATE) return obj
def resource_create_object(request, resource_cls, uri): """In the default bucket, the bucket and collection are implicitly created. This helper instantiate the resource and simulate a request with its RootFactory on the instantiated resource. :returns: the created object :rtype: dict """ resource_name, matchdict = view_lookup(request, uri) # Build a fake request, mainly used to populate the create events that # will be triggered by the resource. fakerequest = build_request(request, { 'method': 'PUT', 'path': uri, }) fakerequest.matchdict = matchdict fakerequest.bound_data = request.bound_data fakerequest.authn_type = request.authn_type fakerequest.selected_userid = request.selected_userid fakerequest.errors = request.errors fakerequest.current_resource_name = resource_name obj_id = matchdict['id'] # Fake context, required to instantiate a resource. context = RouteFactory(fakerequest) context.resource_name = resource_name resource = resource_cls(fakerequest, context) # Check that provided id is valid for this resource. if not resource.model.id_generator.match(obj_id): error_details = { 'location': 'path', 'description': "Invalid %s id" % resource_name } raise_invalid(resource.request, **error_details) data = {'id': obj_id} try: obj = resource.model.create_record(data) # Since the current request is not a resource (but a straight Service), # we simulate a request on a resource. # This will be used in the resource event payload. resource.postprocess(data, action=ACTIONS.CREATE) except storage_exceptions.UnicityError as e: obj = e.record return obj