Example #1
0
File: view.py Project: eliq/stoxy
 def render_delete(self, request):
     name = unicode(parse_path(request.path)[-1])
     existing_object = self.context[name]
     if existing_object:
         del self.context[name]
     else:
         raise NotFound
Example #2
0
File: view.py Project: stoxy/stoxy
    def render_put(self, request):
        existing_object = self.context if not hasattr(request, 'unresolved_path') else None

        requested_type = request.getHeader('content-type')
        content_length = request.getHeader('content-length')

        if requested_type is None:
            log.error('content-type not found in %s', request.getAllHeaders())
            raise BadRequest('No Content-Type specified')

        data = {}
        noncdmi = False

        if requested_type not in self.object_constructor_map.keys():
            noncdmi = True
            dstream = request.content
            data[u'content_length'] = content_length
            data[u'mimetype'] = requested_type
            data[u'value'] = None
            # set to a 'correct' one - the only supported via CDMI
            requested_type = 'application/cdmi-object'
        elif requested_type == 'application/cdmi-object':
            data = self._parse_and_validate_data(request)
            dstream = StringIO.StringIO(data.get('value', ''))
            data[u'value'] = None
        elif requested_type == 'application/cdmi-container':
            dstream = io.BytesIO()
            data = self._parse_and_validate_data(request)
        else:
            raise BadRequest('Cannot handle PUT for the request object type %s' % requested_type)

        if existing_object:
            data[u'name'] = unicode(parse_path(request.path)[-1])
            form = CdmiObjectValidatorFactory.get_applier(existing_object, data)
            request.setHeader('content-type', self.object_type_map[existing_object.type])
            action = 'apply'
        else:
            data[u'name'] = unicode(request.unresolved_path)
            requested_class = self.object_constructor_map[requested_type]
            form = CdmiObjectValidatorFactory.get_creator(requested_class, data)
            request.setHeader('content-type', requested_type)
            action = 'create'

        if form.errors:
            log.error('Validation failed: %s (%s):\n%s', form, request, form.errors)
            request.setResponseCode(BadRequest.status_code)
            return form.error_dict()

        result_object = getattr(form, action)()

        principal = self.get_principal(request)
        d = self.handle_success(None, request, result_object, principal, existing_object, dstream,
                                data.get(u'valuetransferencoding', 'utf-8'))
        connection_lost = request.notifyFinish()
        connection_lost.addBoth(lambda r: d.cancel())
        d.addCallback(self.finish_response, request, result_object, noncdmi, render_value=False)
        d.addErrback(self.handle_error, request, result_object, principal, existing_object)

        return NOT_DONE_YET
Example #3
0
File: view.py Project: stoxy/stoxy
 def render_delete(self, request):
     name = unicode(parse_path(request.path)[-1])
     existing_object = self.context.__parent__[name]
     if existing_object:
         log.debug('Deleting %s', self.context)
         # are we deleting a container?
         if IStorageContainer.providedBy(self.context):
             # check children
             children = [child for child in self.context.listcontent() if
                         IDataObject.providedBy(child) or
                         IStorageContainer.providedBy(child)]
             if len(children) > 0:
                 raise BadRequest('Attempt to delete a non-empty container')
         else:
             # XXX: Alternative authentication methods!
             credentials = request.getHeader('X-Auth-Token')
             storemgr = getAdapter(self.context, IDataStoreFactory).create()
             storemgr.delete(credentials)
         del self.context.__parent__[name]
         handle(self.context, ModelDeletedEvent(self.context.__parent__))
     else:
         raise NotFound
Example #4
0
File: view.py Project: eliq/stoxy
    def render_put(self, request):
        data = self._parse_and_validate_data(request)

        existing_object = self.context if not hasattr(request, 'unresolved_path') else None

        requested_type = request.getHeader('content-type')

        if requested_type is None:
            log.error('content-type not found in %s', request.getAllHeaders())
            raise BadRequest('No Content-Type specified')

        if requested_type not in self.object_constructor_map.keys():
            raise BadRequest('Don\'t know how to create objects of type: %s' % requested_type)

        if existing_object:
            data[u'name'] = unicode(parse_path(request.path)[-1])
            form = CdmiObjectValidatorFactory.get_applier(existing_object, data)
            request.setHeader('content-type', self.object_type_map[existing_object.type])
            action = 'apply'
        else:
            requested_class = self.object_constructor_map[requested_type]
            data[u'name'] = unicode(request.unresolved_path[-1])
            request.setHeader('content-type', requested_type)
            form = CdmiObjectValidatorFactory.get_creator(requested_class, data)
            action = 'create'

        if form.errors:
            log.error('Validation failed: %s (%s):\n%s', form, request, form.errors)
            request.setResponseCode(BadRequest.status_code)
            return form.error_dict()

        result_object = getattr(form, action)()

        @db.transact
        def handle_success(r, request, obj, principal):
            if not existing_object:
                obj.__owner__ = principal
                self.context.add(obj)

            self.add_log_event(principal, '%s of %s (%s) via CDMI was successful' %
                               ('Creation' if not existing_object else 'Update', obj.name, obj.__name__))

        def finish_response(r, request, obj):
            if request.finished:  # Should not be triggered at all
                log.error('Connection lost: cannot render resulting object. '
                          'Modifications were saved. %s', request)
                return
            request.write(self.render_object(obj))
            request.finish()

        def handle_error(f, request, obj, principal):
            f.trap(Exception)
            if request.finished:  # Should not be triggered at all
                try:
                    f.raiseException()
                except Exception:
                    log.error('Connection lost: cannot return error message to the client. %s', request,
                              exc_info=True)
                return

            self.add_log_event(principal, '%s of %s (%s) via CDMI failed: %s: %s' %
                               ('Creation' if not existing_object else 'Update',
                                obj.name, obj.__name__, type(f.value).__name__, f.value))

            request.setResponseCode(500)
            request.write(json.dumps({'errorMessage': str(f.value)}))
            request.finish()

        principal = self.get_principal(request)
        d = handle_success(None, request, result_object, principal)
        connection_lost = request.notifyFinish()
        connection_lost.addCallback(lambda r: d.cancel())
        d.addCallback(finish_response, request, result_object)
        d.addErrback(handle_error, request, result_object, principal)

        return NOT_DONE_YET