コード例 #1
0
    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
コード例 #2
0
ファイル: Resource.py プロジェクト: denishom12/decorator
    def MOVE(self, REQUEST, RESPONSE):
        """Move a resource to a new location. Though we may later try to
        make a move appear seamless across namespaces (e.g. from Zope
        to Apache), MOVE is currently only supported within the Zope
        namespace."""
        self.dav__init(REQUEST, RESPONSE)
        self.dav__validate(self, 'DELETE', REQUEST)
        if not hasattr(aq_base(self), 'cb_isMoveable') or \
           not self.cb_isMoveable():
            raise MethodNotAllowed('This object may not be moved.')

        dest = REQUEST.get_header('Destination', '')

        try:
            path = REQUEST.physicalPathFromURL(dest)
        except ValueError:
            raise BadRequest('No destination given')

        flag = REQUEST.get_header('Overwrite', 'F')
        flag = flag.upper()

        name = path.pop()
        parent_path = '/'.join(path)

        try:
            parent = self.restrictedTraverse(path)
        except ValueError:
            raise Conflict('Attempt to move to an unknown namespace.')
        except 'Not Found':
            raise Conflict('The resource %s must exist.' % parent_path)
        except Exception:
            raise

        if hasattr(parent, '__null_resource__'):
            raise Conflict('The resource %s must exist.' % parent_path)
        existing = hasattr(aq_base(parent), name)
        if existing and flag == 'F':
            raise PreconditionFailed('Resource %s exists.' % dest)
        try:
            parent._checkId(name, allow_dup=1)
        except Exception:
            raise Forbidden(sys.exc_info()[1])
        try:
            parent._verifyObjectPaste(self)
        except Unauthorized:
            raise
        except Exception:
            raise Forbidden(sys.exc_info()[1])

        # Now check locks.  Since we're affecting the resource that we're
        # moving as well as the destination, we have to check both.
        ifhdr = REQUEST.get_header('If', '')
        if existing:
            # The destination itself exists, so we need to check its locks
            destob = aq_base(parent)._getOb(name)
            if IWriteLock.providedBy(destob) and destob.wl_isLocked():
                if ifhdr:
                    itrue = destob.dav__simpleifhandler(
                        REQUEST, RESPONSE, 'MOVE', url=dest, refresh=1)
                    if not itrue:
                        raise PreconditionFailed
                else:
                    raise Locked('Destination is locked.')
        elif IWriteLock.providedBy(parent) and parent.wl_isLocked():
            # There's no existing object in the destination folder, so
            # we need to check the folders locks since we're changing its
            # member list
            if ifhdr:
                itrue = parent.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE',
                                                    col=1, url=dest, refresh=1)
                if not itrue:
                    raise PreconditionFailed('Condition failed.')
            else:
                raise Locked('Destination is locked.')
        if wl_isLocked(self):
            # Lastly, we check ourselves
            if ifhdr:
                itrue = self.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE',
                                                  refresh=1)
                if not itrue:
                    raise PreconditionFailed('Condition failed.')
            else:
                raise Locked('Source is locked and no condition was passed in')

        orig_container = aq_parent(aq_inner(self))
        orig_id = self.getId()

        self._notifyOfCopyTo(parent, op=1)

        notify(ObjectWillBeMovedEvent(self, orig_container, orig_id,
                                      parent, name))

        # try to make ownership explicit so that it gets carried
        # along to the new location if needed.
        self.manage_changeOwnershipType(explicit=1)

        ob = self._getCopy(parent)
        ob._setId(name)

        orig_container._delObject(orig_id, suppress_events=True)

        if existing:
            object = getattr(parent, name)
            self.dav__validate(object, 'DELETE', REQUEST)
            parent._delObject(name)

        parent._setObject(name, ob, set_owner=0, suppress_events=True)
        ob = parent._getOb(name)

        notify(ObjectMovedEvent(ob, orig_container, orig_id, parent, name))
        notifyContainerModified(orig_container)
        if aq_base(orig_container) is not aq_base(parent):
            notifyContainerModified(parent)

        ob._postCopy(parent, op=1)

        # try to make ownership implicit if possible
        ob.manage_changeOwnershipType(explicit=0)

        RESPONSE.setStatus(existing and 204 or 201)
        if not existing:
            RESPONSE.setHeader('Location', dest)
        RESPONSE.setBody('')
        return RESPONSE
コード例 #3
0
    def update(self, context, request):
        """/@@API/update: Update existing object values

        Required parameters:

            - obj_path: path to the object, relative to plone site root.
            - fields: json value, dict: key:value = fieldname:value.

        {
            runtime: Function running time.
            error: true or string(message) if error. false if no error.
            success: true or string(message) if success. false if no success.
            <fieldname>: <current value>
            ...
        }

        So.

        >>> portal = layer['portal']
        >>> portal_url = portal.absolute_url()
        >>> from plone.app.testing import SITE_OWNER_NAME
        >>> from plone.app.testing import SITE_OWNER_PASSWORD

        Update a client's existing address:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/update?", "&".join([
        ... "obj_path=/clients/client-1",
        ... "title=Test",
        ... "PostalAddress={'address': '1 Wendy Way', 'city': 'Johannesburg', 'zip': '9000', 'state': 'Gauteng', 'district': '', 'country':'South Africa'}"
        ... ]))
        >>> browser.contents
        '{..."success": true...}'

        quickly check that it saved:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/read?", "&".join([
        ... "id=client-1",
        ... "include_fields=PostalAddress",
        ... ]))
        >>> browser.contents
        '{...1 Wendy Way...}'

        Try the same with a nonsense fieldname:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/update?", "&".join([
        ... "obj_path=/clients/client-1",
        ... "Thing=Fish",
        ... ]))
        >>> browser.contents
        '{...The following request fields were not used: ...Thing...}'

        Setting the value of a RefereceField to "" or None (null) should not cause
        an error; setting an empty value should clear the field

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/update?", "&".join([
        ... "obj_path=/clients/client-1",
        ... 'DefaultCategories=',
        ... ]))
        >>> browser.contents
        '{..."success": true...}'

        """
        savepoint = transaction.savepoint()
        self.context = context
        self.request = request
        self.unused = [x for x in self.request.form.keys()]
        self.used("form.submitted")
        self.used("__ac_name")
        self.used("__ac_password")
        ret = {
            "url": router.url_for("update", force_external=True),
            "success": False,
            "error": True,
        }
        # always require obj_path
        self.require("obj_path")
        obj_path = self.request['obj_path']
        self.used("obj_path")

        site_path = request['PATH_INFO'].replace("/@@API/update", "")
        obj = context.restrictedTraverse(str(site_path + obj_path))

        try:
            fields = set_fields_from_request(obj, request)
            for field in fields:
                self.used(field)
        except:
            savepoint.rollback()
            raise

        ret['success'] = True
        ret['error'] = False

        if self.unused:
            raise BadRequest(
                "The following request fields were not used: %s.  Request aborted."
                % self.unused)

        return ret
コード例 #4
0
def checkValidId(self, id, allow_dup=0):
    # If allow_dup is false, an error will be raised if an object
    # with the given id already exists. If allow_dup is true,
    # only check that the id string contains no illegal chars;
    # check_valid_id() will be called again later with allow_dup
    # set to false before the object is added.
    if not id or not isinstance(id, str):
        if isinstance(id, text_type):
            id = escape(id, True)
        raise BadRequest('Empty or invalid id specified', id)
    if bad_id(id) is not None:
        raise BadRequest(
            ('The id "%s" contains characters '
             'illegal in URLs.' % escape(id, True)))
    if id in ('.', '..'):
        raise BadRequest(
            'The id "%s" is invalid because it is not traversable.' % id)
    if id.startswith('_'):
        raise BadRequest(
            'The id "%s" is invalid because it '
            'begins with an underscore.' % id)
    if id.startswith('aq_'):
        raise BadRequest(
            'The id "%s" is invalid because it begins with "aq_".' % id)
    if id.endswith('__'):
        raise BadRequest(
            'The id "%s" is invalid because it '
            'ends with two underscores.' % id)
    if id.startswith('@@') or id.startswith('++'):
        raise BadRequest(
            'The id "%s" is invalid because it starts with characters '
            'reserved for Zope views lookup.' % id)
    if not allow_dup:
        obj = getattr(self, id, None)
        if obj is not None:
            # An object by the given id exists either in this
            # ObjectManager or in the acquisition path.
            flags = getattr(obj, '__replaceable__', NOT_REPLACEABLE)
            if hasattr(aq_base(self), id):
                # The object is located in this ObjectManager.
                if not flags & REPLACEABLE:
                    raise BadRequest(
                        'The id "%s" is invalid - it is already in use.' % id)
                # else the object is replaceable even if the UNIQUE
                # flag is set.
            elif flags & UNIQUE:
                raise BadRequest('The id "%s" is reserved.' % id)
    if id == 'REQUEST':
        raise BadRequest('REQUEST is a reserved name.')
    if '/' in id:
        raise BadRequest(
            'The id "%s" contains characters illegal in URLs.' % id)
コード例 #5
0
ファイル: add.py プロジェクト: sauzher/plone.restapi
    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)

        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_))

        # Link translation given the translation_of property
        if PAM_INSTALLED:
            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)

        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
コード例 #6
0
ファイル: create.py プロジェクト: xispa/senaite.core
    def _create_ar(self, context, request):
        """Creates AnalysisRequest object, with supporting Sample, Partition
        and Analysis objects.  The client is retrieved from the obj_path
        key in the request.

        Required request parameters:

            - Contact: One client contact Fullname.  The contact must exist
              in the specified client.  The first Contact with the specified
              value in it's Fullname field will be used.

            - SampleType_<index> - Must be an existing sample type.

        Optional request parameters:

        - CCContacts: A list of contact Fullnames, which will be copied on
          all messages related to this AR and it's sample or results.

        - CCEmails: A list of email addresses to include as above.

        - Sample_id: Create a secondary AR with an existing sample.  If
          unspecified, a new sample is created.

        - Specification: a lookup to set Analysis specs default values
          for all analyses

        - Analysis_Specification: specs (or overrides) per analysis, using
          a special lookup format.

            &Analysis_Specification:list=<Keyword>:min:max:error&...


        """

        wftool = getToolByName(context, 'portal_workflow')
        bc = getToolByName(context, 'bika_catalog')
        bsc = getToolByName(context, 'bika_setup_catalog')
        pc = getToolByName(context, 'portal_catalog')
        ret = {
            "url": router.url_for("create", force_external=True),
            "success": True,
            "error": False,
        }
        SamplingWorkflowEnabled = context.bika_setup.getSamplingWorkflowEnabled(
        )
        for field in [
                'Client', 'SampleType', 'Contact', 'SamplingDate', 'Services'
        ]:
            self.require(field)
            self.used(field)

        try:
            client = resolve_request_lookup(context, request,
                                            'Client')[0].getObject()
        except IndexError:
            raise Exception("Client not found")

        secondary = False
        sample = None
        # Sample_id
        if 'Sample' in request:
            # Secondary AR
            try:
                sample = resolve_request_lookup(context, request,
                                                'Sample')[0].getObject()
            except IndexError:
                raise Exception("Sample not found")
            secondary = True
        else:
            # Primary AR
            sample = _createObjectByType("Sample", client, tmpID())
            sample.unmarkCreationFlag()
            fields = set_fields_from_request(sample, request)
            for field in fields:
                self.used(field)
            sample._renameAfterCreation()
            sample.setSampleID(sample.getId())
            sample.setSamplingWorkflowEnabled(SamplingWorkflowEnabled)
            event.notify(ObjectInitializedEvent(sample))
            sample.at_post_create_script()

        ret['sample_id'] = sample.getId()

        parts = [{
            'services': [],
            'container': [],
            'preservation': '',
            'separate': False
        }]

        specs = self.get_specs_from_request()
        ar = _createObjectByType("AnalysisRequest", client, tmpID())
        ar.unmarkCreationFlag()
        fields = set_fields_from_request(ar, request)
        for field in fields:
            self.used(field)
        ar.setSample(sample)
        ar._renameAfterCreation()
        ret['ar_id'] = ar.getId()

        brains = resolve_request_lookup(context, request, 'Services')
        service_uids = [p.UID for p in brains]
        # If there is a profile, add its services' UIDs
        brains = resolve_request_lookup(context, request, 'Profiles')
        profiles_uids = [p.UID for p in brains]
        profiles_uids = ','.join(profiles_uids)
        profiles_dict = {'Profiles': profiles_uids}
        service_uids = get_services_uids(context=context,
                                         analyses_serv=service_uids,
                                         values=profiles_dict)
        ar.setAnalyses(service_uids, specs=specs)
        new_analyses = ar.getAnalyses(full_objects=True)
        ar.reindexObject()
        event.notify(ObjectInitializedEvent(ar))
        ar.at_post_create_script()

        # Create sample partitions
        parts_and_services = {}
        for _i in range(len(parts)):
            p = parts[_i]
            part_prefix = sample.getId() + "-P"
            if '%s%s' % (part_prefix, _i + 1) in sample.objectIds():
                parts[_i]['object'] = sample['%s%s' % (part_prefix, _i + 1)]
                parts_and_services['%s%s' %
                                   (part_prefix, _i + 1)] = p['services']
                part = parts[_i]['object']
            else:
                part = _createObjectByType("SamplePartition", sample, tmpID())
                parts[_i]['object'] = part
                container = None
                preservation = p['preservation']
                parts[_i]['prepreserved'] = False
                part.edit(
                    Container=container,
                    Preservation=preservation,
                )
                part.processForm()
                parts_and_services[part.id] = p['services']

        # Add analyses to sample partitions
        # XXX jsonapi create AR: right now, all new analyses are linked to the first samplepartition
        if new_analyses:
            analyses = list(part.getAnalyses())
            analyses.extend(new_analyses)
            for analysis in new_analyses:
                analysis.setSamplePartition(part)
            part.setAnalyses(analyses)

        action = 'no_sampling_workflow'
        if SamplingWorkflowEnabled:
            action = 'sampling_workflow'
        wftool.doActionFor(ar, action)

        if secondary:
            # If secondary AR, then we need to manually transition the AR (and its
            # children) to fit with the Sample Partition's current state
            sampleactions = getReviewHistoryActionsList(sample)
            doActionsFor(ar, sampleactions)

        else:
            # If Preservation is required for some partitions,
            # and the SamplingWorkflow is disabled, we need
            # to transition to to_be_preserved manually.
            if not SamplingWorkflowEnabled:
                to_be_preserved = []
                sample_due = []
                lowest_state = 'sample_due'
                for p in sample.objectValues('SamplePartition'):
                    if p.getPreservation():
                        lowest_state = 'to_be_preserved'
                        to_be_preserved.append(p)
                    else:
                        sample_due.append(p)
                for p in to_be_preserved:
                    doActionFor(p, 'to_be_preserved')
                for p in sample_due:
                    doActionFor(p, 'sample_due')
                doActionFor(sample, lowest_state)

            # Transition pre-preserved partitions
            for p in parts:
                if 'prepreserved' in p and p['prepreserved']:
                    part = p['object']
                    state = workflow.getInfoFor(part, 'review_state')
                    if state == 'to_be_preserved':
                        doActionFor(part, 'preserve')

        if self.unused:
            raise BadRequest(
                "The following request fields were not used: %s.  Request aborted."
                % self.unused)

        return ret
コード例 #7
0
    def __call__(self,
                 validate_all=False,
                 data=None,
                 create=False):  # noqa: ignore=C901
        if data is None:
            data = json_body(self.request)

        modified = {}
        schema_data = {}
        errors = []

        for schema in iterSchemata(self.context):
            write_permissions = mergedTaggedValueDict(schema,
                                                      WRITE_PERMISSIONS_KEY)

            for name, field in getFields(schema).items():

                field_data = schema_data.setdefault(schema, {})

                if field.readonly:
                    continue

                if name in data:
                    dm = queryMultiAdapter((self.context, field), IDataManager)
                    if not dm.canWrite():
                        continue

                    if not self.check_permission(write_permissions.get(name)):
                        continue

                    # set the field to missing_value if we receive null
                    if data[name] is None:
                        if not field.required:
                            dm.set(field.missing_value)
                        else:
                            errors.append({
                                "field":
                                field.__name__,
                                "message": (
                                    "{} is a required field.".format(
                                        field.__name__),
                                    "Setting it to null is not allowed.",
                                ),
                            })
                        continue

                    # Deserialize to field value
                    deserializer = queryMultiAdapter(
                        (field, self.context, self.request),
                        IFieldDeserializer)
                    if deserializer is None:
                        continue

                    try:
                        value = deserializer(data[name])
                    except ValueError as e:
                        errors.append({
                            "message": str(e),
                            "field": name,
                            "error": e
                        })
                    except ValidationError as e:
                        errors.append({
                            "message": e.doc(),
                            "field": name,
                            "error": e
                        })
                    else:
                        field_data[name] = value
                        if value != dm.get():
                            dm.set(value)
                            # Collect the names of the modified fields
                            # Use prefixed name because z3c.form does so
                            prefixed_name = schema.__name__ + "." + name
                            modified.setdefault(schema,
                                                []).append(prefixed_name)

                elif validate_all:
                    # Never validate the changeNote of p.a.versioningbehavior
                    # The Versionable adapter always returns an empty string
                    # which is the wrong type. Should be unicode and should be
                    # fixed in p.a.versioningbehavior
                    if name == "changeNote":
                        continue
                    dm = queryMultiAdapter((self.context, field), IDataManager)
                    bound = field.bind(self.context)
                    try:
                        bound.validate(dm.get())
                    except ValidationError as e:
                        errors.append({
                            "message": e.doc(),
                            "field": name,
                            "error": e
                        })

        # Validate schemata
        for schema, field_data in schema_data.items():
            validator = queryMultiAdapter(
                (self.context, self.request, None, schema, None),
                IManagerValidator)
            for error in validator.validate(field_data):
                errors.append({"error": error, "message": str(error)})

        if errors:
            raise BadRequest(errors)

        # We'll set the layout after the validation and and even if there
        # are no other changes.
        if "layout" in data:
            layout = data["layout"]
            self.context.setLayout(layout)

        # OrderingMixin
        self.handle_ordering(data)

        if modified and not create:
            descriptions = []
            for interface, names in modified.items():
                descriptions.append(Attributes(interface, *names))
            notify(ObjectModifiedEvent(self.context, *descriptions))

        return self.context
コード例 #8
0
 def f():
     raise BadRequest("argh")
コード例 #9
0
 def lookup_object(dataself, data):
     oguid = Oguid.parse(data.get('oguid'))
     obj = oguid.resolve_object()
     if not obj:
         raise BadRequest('Invalid oguid, could not be resolved.')
     return obj
コード例 #10
0
 def badRequestError(self, v=''):
     """Raise an error indicating something wrong with the request"""
     raise BadRequest(v)
コード例 #11
0
ファイル: add.py プロジェクト: FHNW/plone.restapi
    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)

        # Generate a temporary id if the id is not given
        if not id_:
            now = DateTime()
            new_id = '{}.{}.{}{:04d}'.format(type_.lower().replace(' ', '_'),
                                             now.strftime('%Y-%m-%d'),
                                             str(now.millis())[7:],
                                             randint(0, 9999))
        else:
            new_id = id_

        # Create object
        try:
            new_id = self.context.invokeFactory(type_, new_id, title=title)
        except BadRequest as e:
            self.request.response.setStatus(400)
            return dict(error=dict(type='DeserializationError',
                                   message=str(e.message)))
        except ValueError as e:
            self.request.response.setStatus(400)
            return dict(error=dict(type='DeserializationError',
                                   message=str(e.message)))

        # Update fields
        obj = self.context[new_id]
        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_:
            self.rename_object(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
コード例 #12
0
    def __call__(self):
        state = self.request.form.get('state')
        messages = IStatusMessage(self.request)
        translator = self.context.translate
        navigation_root = api.portal.get_navigation_root(context=self.context)
        if 'error' in self.request.form:
            messages = IStatusMessage(self.request)
            reason = self.request.form.get('error')

            # noinspection PyArgumentList
            messages.add(translator(
                _(u'message_%s_failed' % state, mapping={u'reason':
                                                         reason}), ),
                         type='error')

            self.request.response.redirect(navigation_root.absolute_url() +
                                           '/@@id4me')
            return

        if 'code' not in self.request.form:
            raise BadRequest('no code given')

        code = self.request.form.get('code')

        if state == 'login':
            user = self.auth_util.verify_user_login(code)
            if user:
                acl_users = getToolByName(self.context, 'acl_users')

                # noinspection PyProtectedMember
                acl_users.session._setupSession(user.getId(),
                                                self.request.response)

                # noinspection PyArgumentList
                messages.add(translator(_(u'message_login_successful')),
                             type='info')

                self.request.response.redirect(navigation_root.absolute_url())
            else:
                # noinspection PyArgumentList
                messages.add(translator(_(u'message_no_user_connected')),
                             type='error')

                self.request.response.redirect(navigation_root.absolute_url() +
                                               '/@@id4me')
        elif state == 'register':
            if not api.portal.get_registry_record(
                    name='plone.enable_self_reg'):
                raise Forbidden()

            user = self.auth_util.register_user(code)

            acl_users = getToolByName(self.context, 'acl_users')

            # noinspection PyProtectedMember
            acl_users.session._setupSession(user.getId(),
                                            self.request.response)

            # noinspection PyArgumentList
            messages.add(translator(
                _(u'message_account_created',
                  mapping={u'user_id': user.getId()})),
                         type='info')

            self.request.response.redirect(navigation_root.absolute_url())
        elif state == 'connect':
            if api.user.is_anonymous():
                raise Forbidden('No user logged in')
            user = api.user.get_current()

            self.auth_util.connect_user_login(user=user, code=code)

            # noinspection PyArgumentList
            messages.add(
                translator(
                    _(
                        u'message_login_connected',
                        # ToDo: get Identity Agent information
                        mapping={u'agent': 'NOT_FOUND'})),
                type='info')

            self.request.response.redirect(navigation_root.absolute_url())
        else:
            # ToDo: handle Case
            raise BadRequest('no state given')
コード例 #13
0
    def reply(self):
        portal = getSite()
        data = json_body(self.request)

        groupname = data.get("groupname", None)

        if not groupname:
            raise BadRequest("Property 'groupname' is required")

        email = data.get("email", None)
        title = data.get("title", None)
        description = data.get("description", None)
        roles = data.get("roles", None)
        groups = data.get("groups", None)
        users = data.get("users", [])

        properties = {
            "title": title,
            "description": description,
            "email": email
        }

        gtool = getToolByName(self.context, "portal_groups")
        regtool = getToolByName(self.context, "portal_registration")

        if not regtool.isMemberIdAllowed(groupname):
            raise BadRequest("The group name you entered is not valid.")

        already_exists = gtool.getGroupById(groupname)
        if already_exists:
            raise BadRequest("The group name you entered already exists.")

        # Disable CSRF protection
        if "IDisableCSRFProtection" in dir(plone.protect.interfaces):
            alsoProvides(self.request,
                         plone.protect.interfaces.IDisableCSRFProtection)

        success = gtool.addGroup(
            groupname,
            roles,
            groups,
            properties=properties,
            title=title,
            description=description,
        )
        if not success:
            raise BadRequest(
                "Error occurred, could not add group {}.".format(groupname))

        # Add members
        group = gtool.getGroupById(groupname)
        for userid in users:
            group.addMember(userid)

        self.request.response.setStatus(201)
        # Note: to please Zope 4.5.2+ we make sure the header is a string,
        # and not unicode on Python 2.
        if six.PY2 and not isinstance(groupname, str):
            groupname = groupname.encode("utf-8")
        self.request.response.setHeader(
            "Location",
            portal.absolute_url() + "/@groups/" + groupname)
        serializer = queryMultiAdapter((group, self.request), ISerializeToJson)
        return serializer()
コード例 #14
0
    def _initProperties(self, node):
        obj = self.context
        if node.hasAttribute('i18n:domain'):
            i18n_domain = str(node.getAttribute('i18n:domain'))
            obj._updateProperty('i18n_domain', i18n_domain)
        for child in node.childNodes:
            if child.nodeName != 'property':
                continue
            prop_id = str(child.getAttribute('name'))
            prop_map = obj.propdict().get(prop_id, None)

            if prop_map is None:
                if child.hasAttribute('type'):
                    val = str(child.getAttribute('select_variable'))
                    prop_type = str(child.getAttribute('type'))
                    obj._setProperty(prop_id, val, prop_type)
                    prop_map = obj.propdict().get(prop_id, None)
                else:
                    raise ValueError("undefined property '%s'" % prop_id)

            if not 'w' in prop_map.get('mode', 'wd'):
                raise BadRequest('%s cannot be changed' % prop_id)

            elements = []
            remove_elements = []
            for sub in child.childNodes:
                if sub.nodeName == 'element':
                    if len(sub.childNodes) > 0:
                        value = sub.childNodes[0].nodeValue.strip()
                        if isinstance(value, unicode):
                            value = value.encode(self._encoding)
                        if self._convertToBoolean(
                                sub.getAttribute('remove') or 'False'):
                            remove_elements.append(value)
                            if value in elements:
                                elements.remove(value)
                        else:
                            elements.append(value)
                            if value in remove_elements:
                                remove_elements.remove(value)

            if elements or prop_map.get('type') == 'multiple selection':
                prop_value = tuple(elements) or ()
            elif prop_map.get('type') == 'boolean':
                prop_value = self._convertToBoolean(self._getNodeText(child))
            else:
                # if we pass a *string* to _updateProperty, all other values
                # are converted to the right type
                prop_value = self._getNodeText(child).encode(self._encoding)

            if not self._convertToBoolean(
                    child.getAttribute('purge') or 'True'):
                # If the purge attribute is False, merge sequences
                prop = obj.getProperty(prop_id)
                if isinstance(prop, (tuple, list)):
                    prop_value = (tuple([
                        p for p in prop
                        if p not in prop_value and p not in remove_elements
                    ]) + tuple(prop_value))

            obj._updateProperty(prop_id, prop_value)
コード例 #15
0
ファイル: update.py プロジェクト: Espurna/senaite.core
    def update_many(self, context, request):
        """/@@API/update_many: Update existing object values

        This is a wrapper around the update method, allowing multiple updates
        to be combined into a single request.

        required parameters:

            - input_values: A json-encoded dictionary.
              Each key is an obj_path, and each value is a dictionary
              containing key/value pairs to be set on the object.

        Return value:

        {
            runtime: Function running time.
            error: true or string(message) if error. false if no error.
            success: true or string(message) if success. false if no success.
            updates: return values from update
        }
        """
        self.context = context
        self.request = request
        self.unused = [x for x in self.request.form.keys()]
        self.used("form.submitted")
        self.used("__ac_name")
        self.used("__ac_password")
        ret = {
            "url": router.url_for("update_many", force_external=True),
            "success": False,
            "error": True,
            "updates": [],
        }

        input_values = json.loads(request.get('input_values', '[]'))
        if not input_values:
            raise BadRequest("missing input_values")
        site_path = request['PATH_INFO'].replace("/@@API/update_many", "")

        for obj_path, i in input_values.items():
            savepoint = transaction.savepoint()
            if not obj_path.startswith("/"):
                obj_path = "/" + obj_path
            if obj_path.startswith(site_path):
                obj_path = obj_path[len(site_path):]
            obj = context.restrictedTraverse(str(site_path + obj_path))
            this_ret = {
                "url": router.url_for("update_many", force_external=True),
                "success": False,
                "error": True,
            }
            try:
                fields = set_fields_from_request(obj, i)
                if not fields:
                    this_ret['success'] = False
                    this_ret['error'] = True
                else:
                    this_ret['success'] = True
                    this_ret['error'] = False
            except:
                savepoint.rollback()
                raise
            ret['updates'].append(this_ret)
        ret['success'] = True
        ret['error'] = False
        return ret
コード例 #16
0
 def validate_data(self, data):
     if not data.get('oguid'):
         raise BadRequest('Missing parameter oguid')
     return data
コード例 #17
0
ファイル: update.py プロジェクト: Espurna/senaite.core
    def update(self, context, request):
        """/@@API/update: Update existing object values

        Required parameters:

            - obj_path: path to the object, relative to plone site root.
            - fields: json value, dict: key:value = fieldname:value.

        {
            runtime: Function running time.
            error: true or string(message) if error. false if no error.
            success: true or string(message) if success. false if no success.
            <fieldname>: <current value>
            ...
        }

        So.

        >>> portal = layer['portal']
        >>> portal_url = portal.absolute_url()
        >>> from plone.app.testing import SITE_OWNER_NAME
        >>> from plone.app.testing import SITE_OWNER_PASSWORD

        Update a client's existing address:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/update?", "&".join([
        ... "obj_path=/clients/client-1",
        ... "title=Test",
        ... "PostalAddress={'address': '1 Wendy Way', 'city': 'Johannesburg', 'zip': '9000', 'state': 'Gauteng', 'district': '', 'country':'South Africa'}"
        ... ]))
        >>> browser.contents
        '{..."success": true...}'

        quickly check that it saved:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/read?", "&".join([
        ... "id=client-1",
        ... "include_fields=PostalAddress",
        ... ]))
        >>> browser.contents
        '{...1 Wendy Way...}'

        Try the same with a nonsense fieldname:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/update?", "&".join([
        ... "obj_path=/clients/client-1",
        ... "Thing=Fish",
        ... ]))
        >>> browser.contents
        '{...The following request fields were not used: ...Thing...}'

        Setting the value of a RefereceField to "" or None (null) should not cause
        an error; setting an empty value should clear the field

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/update?", "&".join([
        ... "obj_path=/clients/client-1",
        ... 'DefaultCategories=',
        ... ]))
        >>> browser.contents
        '{..."success": true...}'

        """
        savepoint = transaction.savepoint()
        self.context = context
        self.request = request
        self.unused = [x for x in self.request.form.keys()]
        self.used("form.submitted")
        self.used("__ac_name")
        self.used("__ac_password")
        ret = {
            "url": router.url_for("update", force_external=True),
            "success": False,
            "error": True,
        }
        obj = None
        # Find out if the object can be retrieved via UID or via
        # traversing.
        if self.request.get('obj_uid', ''):
            uc = getToolByName(self.context, 'uid_catalog')
            brain = uc(UID=self.request.get('obj_uid', ''))
            obj = brain[0].getObject() if brain else None
        if self.request.get('obj_path', '') and not obj:
            obj_path = self.request['obj_path']
            site_path = context.portal_url.getPortalObject().getPhysicalPath()
            if site_path and isinstance(site_path, basestring):
                site_path = site_path if site_path.startswith(
                    '/') else '/' + site_path
                obj = context.restrictedTraverse(site_path + obj_path)
            elif site_path and len(site_path) > 1:
                site_path = site_path[1]
                site_path = site_path if site_path.startswith(
                    '/') else '/' + site_path
                obj = context.restrictedTraverse(site_path + obj_path)

        if obj:
            self.used('obj_uid')
            self.used('obj_path')
        else:
            ret['success'] = False
            ret['error'] = True
            return ret

        try:
            fields = set_fields_from_request(obj, request)
            if not fields:
                return ret
            for field in fields:
                self.used(field)
        except:
            savepoint.rollback()
            raise

        ret['success'] = True
        ret['error'] = False

        if self.unused:
            raise BadRequest(
                "The following request fields were not used: %s.  Request aborted."
                % self.unused)

        return ret
コード例 #18
0
 def get_userid(self):
     if len(self.params) != 1:
         raise BadRequest("Must supply user ID as URL path parameters.")
     return self.params[0]
コード例 #19
0
ファイル: create.py プロジェクト: xispa/senaite.core
    def create(self, context, request):
        """/@@API/create: Create new object.

        Required parameters:

            - obj_type = portal_type of new object.
            - obj_path = path of new object, from plone site root. - Not required for
             obj_type=AnalysisRequest

        Optionally:

            - obj_id = ID of new object.

        All other parameters in the request are matched against the object's
        Schema.  If a matching field is found in the schema, then the value is
        taken from the request and sent to the field's mutator.

        Reference fields may have their target value(s) specified with a
        delimited string query syntax, containing the portal_catalog search:

            <FieldName>=index1:value1|index2:value2

        eg to set the Client of a batch:

            ...@@API/update?obj_path=<path>...
            ...&Client=title:<client_title>&...

        And, to set a multi-valued reference, these both work:

            ...@@API/update?obj_path=<path>...
            ...&InheritedObjects:list=title:AR1...
            ...&InheritedObjects:list=title:AR2...

            ...@@API/update?obj_path=<path>...
            ...&InheritedObjects[]=title:AR1...
            ...&InheritedObjects[]=title:AR2...

        The Analysis_Specification parameter is special, it mimics
        the format of the python dictionaries, and only service Keyword
        can be used to reference services.  Even if the keyword is not
        actively required, it must be supplied:

            <service_keyword>:min:max:error tolerance

        The function returns a dictionary as a json string:

        {
            runtime: Function running time.
            error: true or string(message) if error. false if no error.
            success: true or string(message) if success. false if no success.
        }

        >>> portal = layer['portal']
        >>> portal_url = portal.absolute_url()
        >>> from plone.app.testing import SITE_OWNER_NAME
        >>> from plone.app.testing import SITE_OWNER_PASSWORD

        Simple AR creation, no obj_path parameter is required:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/create", "&".join([
        ... "obj_type=AnalysisRequest",
        ... "Client=portal_type:Client|id:client-1",
        ... "SampleType=portal_type:SampleType|title:Apple Pulp",
        ... "Contact=portal_type:Contact|getFullname:Rita Mohale",
        ... "Services:list=portal_type:AnalysisService|title:Calcium",
        ... "Services:list=portal_type:AnalysisService|title:Copper",
        ... "Services:list=portal_type:AnalysisService|title:Magnesium",
        ... "SamplingDate=2013-09-29",
        ... "Specification=portal_type:AnalysisSpec|title:Apple Pulp",
        ... ]))
        >>> browser.contents
        '{..."success": true...}'

        If some parameters are specified and are not located as existing fields or properties
        of the created instance, the create should fail:

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/create?", "&".join([
        ... "obj_type=Batch",
        ... "obj_path=/batches",
        ... "title=Test",
        ... "Thing=Fish"
        ... ]))
        >>> browser.contents
        '{...The following request fields were not used: ...Thing...}'

        Now we test that the AR create also fails if some fields are spelled wrong

        >>> browser = layer['getBrowser'](portal, loggedIn=True, username=SITE_OWNER_NAME, password=SITE_OWNER_PASSWORD)
        >>> browser.open(portal_url+"/@@API/create", "&".join([
        ... "obj_type=AnalysisRequest",
        ... "thing=Fish",
        ... "Client=portal_type:Client|id:client-1",
        ... "SampleType=portal_type:SampleType|title:Apple Pulp",
        ... "Contact=portal_type:Contact|getFullname:Rita Mohale",
        ... "Services:list=portal_type:AnalysisService|title:Calcium",
        ... "Services:list=portal_type:AnalysisService|title:Copper",
        ... "Services:list=portal_type:AnalysisService|title:Magnesium",
        ... "SamplingDate=2013-09-29"
        ... ]))
        >>> browser.contents
        '{...The following request fields were not used: ...thing...}'

        """
        savepoint = transaction.savepoint()
        self.context = context
        self.request = request
        self.unused = [x for x in self.request.form.keys()]
        self.used("form.submitted")
        self.used("__ac_name")
        self.used("__ac_password")
        # always require obj_type
        self.require("obj_type")
        obj_type = self.request['obj_type']
        self.used("obj_type")
        # AnalysisRequest shortcut: creates Sample, Partition, AR, Analyses.
        if obj_type == "AnalysisRequest":
            try:
                return self._create_ar(context, request)
            except:
                savepoint.rollback()
                raise
        # Other object types require explicit path as their parent
        self.require("obj_path")
        obj_path = self.request['obj_path']
        if not obj_path.startswith("/"):
            obj_path = "/" + obj_path
        self.used("obj_path")
        site_path = request['PATH_INFO'].replace("/@@API/create", "")
        parent = context.restrictedTraverse(str(site_path + obj_path))
        # normal permissions still apply for this user
        if not getSecurityManager().checkPermission(AccessJSONAPI, parent):
            msg = "You don't have the '{0}' permission on {1}".format(
                AccessJSONAPI, parent.absolute_url())
            raise Unauthorized(msg)

        obj_id = request.get("obj_id", "")
        _renameAfterCreation = False
        if not obj_id:
            _renameAfterCreation = True
            obj_id = tmpID()
        self.used(obj_id)

        ret = {
            "url": router.url_for("create", force_external=True),
            "success": True,
            "error": False,
        }

        try:
            obj = _createObjectByType(obj_type, parent, obj_id)
            obj.unmarkCreationFlag()
            if _renameAfterCreation:
                renameAfterCreation(obj)
            ret['obj_id'] = obj.getId()
            ret['obj_uid'] = obj.UID()
            used_fields = set_fields_from_request(obj, request)
            for field in used_fields:
                self.used(field)
            obj.reindexObject()
            obj.aq_parent.reindexObject()
            event.notify(ObjectInitializedEvent(obj))
            obj.at_post_create_script()
        except:
            savepoint.rollback()
            raise

        if self.unused:
            raise BadRequest(
                "The following request fields were not used: %s.  Request aborted."
                % self.unused)

        return ret
コード例 #20
0
ファイル: userfolder.py プロジェクト: py361/Zope
 def _delUsers(self, names, REQUEST=None):
     if not names:
         raise BadRequest('No users specified')
     self._doDelUsers(names)
     if REQUEST:
         return self._mainUser(self, REQUEST)
コード例 #21
0
    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
コード例 #22
0
    def calculate_partitions(self, context, request):
        """Calculate the size and type of sample partitions required to perform
        analysis services on a certain sample type.

        Required fields

            - services: A list of Analysis Services
            - sampletype: The sample type in use for this sample

        Example usage:

            @@API/calculate_partitions
                ?sampletype=portal_type:SampleType,title=Cattle Feed
                &services:list=portal_type:AnalysisService,title:Ash
                &services:list=portal_type:AnalysisService,title:Moisture
        """

        ret = {
            "url": router.url_for("calculate_partitions", force_external=True),
            "success": False,
            "error": True,
        }
        parts = []

        uc = getToolByName(context, 'uid_catalog')

        services = []
        _services = request.get('services', '').split(",")
        if not _services:
            raise BadRequest("services are not present in request")
        for uid in _services:
            if not uid:
                continue
            try:
                services.append(uc(UID=uid)[0].getObject())
            except:
                raise BadRequest("analysis service uid %s is invalid" % uid)

        _sampletype = request.get('sampletype', '')
        if not _sampletype:
            raise BadRequest("sampletype is not present in the request")
        try:
            sampletype = uc(UID=_sampletype)[0].getObject()
        except:
            raise BadRequest("sample type %s is invalid" % _sampletype)

        for service in services:
            partsetup = [
                ps for ps in service.getPartitionSetup()
                if ps['sampletype'] == sampletype.UID()
            ]
            if partsetup:
                # User values set for each SampleType on each service
                separate = bool(partsetup[0]['separate'])
                containers = [
                    uc(UID=uid)[0].getObject()
                    for uid in partsetup[0]['container']
                ]
                preservations = [
                    uc(UID=uid)[0].getObject()
                    for uid in partsetup[0]['preservation']
                ]
                minvol = mg(partsetup[0]['vol'])
            else:
                # read default values from service
                separate = service.getSeparate()
                containers = service.getContainer()
                if not containers:
                    containers = []
                if containers and not type(containers) in (list, tuple):
                    containers = [
                        containers,
                    ]
                preservations = service.getPreservation()
                if not preservations:
                    preservations = []
                if preservations and not type(preservations) in (list, tuple):
                    preservations = [
                        preservations,
                    ]
                minvol = mg(sampletype.getMinimumVolume())

            # ContainerTypes may also be selected in the UI.
            # we want a list of actual containers which this analysis can use
            _containers = []
            for c in containers:
                if c.portal_type == 'Container':
                    _containers.append(c)
                else:
                    _containers.extend(c.getContainers())
            containers = _containers

            containers.sort(
                lambda a, b: cmp(mg(a.getCapacity()), mg(b.getCapacity())))

            if separate:
                parts.append({
                    'services': [
                        service,
                    ],
                    'separate': True,
                    'container': containers,
                    'preservation': preservations,
                    'minvol': minvol,
                })
            else:
                # find partition this analysis can use or create new entry.
                for x, part in enumerate(parts):
                    if part['separate']:
                        continue

                    # our container must match this part.
                    _containers = []
                    if part['container']:
                        _containers = [
                            c for c in part['container'] if c in containers
                        ]
                        if not _containers:
                            continue

                    # our preservation must match this part
                    _preservations = []
                    if part['preservation']:
                        _preservations = [
                            p for p in part['preservation']
                            if p in preservations
                        ]
                        if not _preservations:
                            continue

                    # filter containers on capacoty
                    _required_vol = part['minvol'] + minvol
                    if _containers:
                        _containers = [
                            c for c in _containers
                            if mg(c.getCapacity()) > _required_vol
                        ]
                        if not _containers:
                            continue

                    # all the conditions passed:
                    # this partition can host our analysis
                    part['minvol'] = _required_vol
                    part['services'].append(service)
                    part['container'] = _containers
                    part['preservation'] = _preservations
                    parts[x] = part
                    break
                # no partition found to share this analysis: create new.
                else:
                    parts.append({
                        'services': [
                            service,
                        ],
                        'separate': False,
                        'container': containers,
                        'preservation': preservations,
                        'minvol': minvol
                    })

        # Convert objects to UIDs
        for x, part in enumerate(parts):
            parts[x]['service_titles'] = [s.Title() for s in part['services']]
            parts[x]['services'] = [s.UID() for s in part['services']]
            parts[x]['container_titles'] = [
                c.Title() for c in part['container']
            ]
            parts[x]['container'] = [c.UID() for c in part['container']]
            parts[x]['preservation_titles'] = [
                p.Title() for p in part['preservation']
            ]
            parts[x]['preservation'] = [p.UID() for p in part['preservation']]
            parts[x]['minvol'] = str(part['minvol'])

        ret['success'] = True
        ret['error'] = False
        ret['parts'] = parts

        return ret
コード例 #23
0
    def apply(self, obj, url=None, depth=0, result=None, top=1):
        if result is None:
            result = StringIO()
            depth = self.depth
            url = urlfix(self.request['URL'], 'PROPFIND')
            url = urlbase(url)
            result.write('<?xml version="1.0" encoding="utf-8"?>\n'
                         '<d:multistatus xmlns:d="DAV:">\n')
        iscol = isDavCollection(obj)
        if iscol and url[-1] != '/':
            url = url + '/'
        result.write('<d:response>\n<d:href>%s</d:href>\n' % safe_quote(url))
        if hasattr(aq_base(obj), 'propertysheets'):
            propsets = obj.propertysheets.values()
            obsheets = obj.propertysheets
        else:
            davprops = DAVProps(obj)
            propsets = (davprops, )
            obsheets = {'DAV:': davprops}
        if self.allprop:
            stats = []
            for ps in propsets:
                if hasattr(aq_base(ps), 'dav__allprop'):
                    stats.append(ps.dav__allprop())
            stats = ''.join(stats) or '<d:status>200 OK</d:status>\n'
            result.write(stats)
        elif self.propname:
            stats = []
            for ps in propsets:
                if hasattr(aq_base(ps), 'dav__propnames'):
                    stats.append(ps.dav__propnames())
            stats = ''.join(stats) or '<d:status>200 OK</d:status>\n'
            result.write(stats)
        elif self.propnames:
            rdict = {}
            for name, ns in self.propnames:
                ps = obsheets.get(ns, None)
                if ps is not None and hasattr(aq_base(ps), 'dav__propstat'):
                    ps.dav__propstat(name, rdict)
                else:
                    prop = '<n:%s xmlns:n="%s"/>' % (name, ns)
                    code = '404 Not Found'
                    if code not in rdict:
                        rdict[code] = [prop]
                    else:
                        rdict[code].append(prop)
            keys = rdict.keys()
            keys.sort()
            for key in keys:
                result.write('<d:propstat>\n' '  <d:prop>\n')
                map(result.write, rdict[key])
                result.write('  </d:prop>\n'
                             '  <d:status>HTTP/1.1 %s</d:status>\n'
                             '</d:propstat>\n' % key)
        else:
            raise BadRequest('Invalid request')
        result.write('</d:response>\n')
        if depth in ('1', 'infinity') and iscol:
            for ob in obj.listDAVObjects():
                if hasattr(ob, "meta_type"):
                    if ob.meta_type == "Broken Because Product is Gone":
                        continue
                dflag = hasattr(ob, '_p_changed') and (ob._p_changed is None)
                if hasattr(ob, '__locknull_resource__'):
                    # Do nothing, a null resource shouldn't show up to DAV
                    if dflag:
                        ob._p_deactivate()
                elif hasattr(ob, '__dav_resource__'):
                    uri = urljoin(url, absattr(ob.getId()))
                    depth = depth == 'infinity' and depth or 0
                    self.apply(ob, uri, depth, result, top=0)
                    if dflag:
                        ob._p_deactivate()
        if not top:
            return result
        result.write('</d:multistatus>')

        return result.getvalue()
コード例 #24
0
 def _checkId(self, id, allow_dup=0):
     wf_def = aq_parent(aq_inner(self))
     if id == wf_def.state_var:
         raise BadRequest('"%s" is used for keeping state.' % id)
     return ContainerTab._checkId(self, id, allow_dup)
コード例 #25
0
    def getQuestionData(self, dbQn, dbLec):
        """Fetch dict for question, obsfucating the answer"""
        out = None

        def getQuestionDict(plonePath):
            if '?' in plonePath:
                (plonePath, querystring) = plonePath.split('?', 1)
                querystring = urlparse.parse_qs(querystring)
            else:
                querystring = {}

            try:
                #NB: Unrestricted so we can see this even when direct access is banned
                dataView = self.portalObject().unrestrictedTraverse(
                    str(plonePath) + '/@@data')
            except KeyError:
                raise NotFound(self, str(plonePath), self.request)
            return dataView.asDict(querystring)

        # Is the student requesting a particular question they've done before?
        if not out and dbQn.qnType == 'tw_questiontemplate' and 'question_id' in self.request.form and 'author_qn' not in self.request.form:
            student = self.getCurrentStudent()

            ugQn = (Session.query(db.UserGeneratedQuestion).filter(
                db.UserGeneratedQuestion.ugQuestionGuid ==
                self.request.form['question_id']).filter(
                    db.UserGeneratedQuestion.questionId ==
                    dbQn.questionId).filter(
                        db.UserGeneratedQuestion.studentId != student.studentId
                    ).first())
            if ugQn is not None:
                # Found one, should return it
                out = self.ugQuestionToJson(ugQn)
            else:
                raise NotFound(self, self.request.form['question_id'],
                               self.request)

        # If a questiontemplate, might want a student to evaluate a question
        if not out and dbQn.qnType == 'tw_questiontemplate':
            student = self.getCurrentStudent()

            # Fetch value of required settings
            settings = getStudentSettings(dbLec, student)
            setting_values = dict(
                prob_template_eval=float(
                    settings.get('prob_template_eval', 0.8)),
                cap_template_qns=int(settings.get('cap_template_qns', 5)),
                cap_template_qn_reviews=int(
                    settings.get('cap_template_qn_reviews', 10)),
                cap_template_qn_nonsense=int(
                    settings.get('cap_template_qn_nonsense', 10)),
            )

            # Should the user be reviewing a question?
            if self.request.form.get('author_qn', False):
                reviewQuestion = False
            elif (random.random() <= setting_values['prob_template_eval']):
                reviewQuestion = True
            elif setting_values['cap_template_qns'] > 0:
                reviewQuestion = (Session.query(
                    db.UserGeneratedQuestion).filter(
                        db.UserGeneratedQuestion.questionId == dbQn.questionId
                    ).filter(
                        db.UserGeneratedQuestion.studentId == student.studentId
                    ).count()) >= setting_values['cap_template_qns']
            else:
                reviewQuestion = False

            if reviewQuestion:
                # Generate query of all irrelevant questions; either the student already reviewed it
                ugAnswerQuery = (Session.query(
                    db.UserGeneratedAnswer.ugQuestionGuid).filter(
                        db.UserGeneratedAnswer.studentId == student.studentId))
                # ...or that question has reached it's review cap
                ugAnswerQuery = ugAnswerQuery.union(
                    Session.query(db.UserGeneratedAnswer.ugQuestionGuid).
                    group_by(db.UserGeneratedAnswer.ugQuestionGuid).having(
                        or_(
                            func.count(db.UserGeneratedAnswer.ugAnswerId) >=
                            setting_values['cap_template_qn_reviews'],
                            and_(
                                func.count(db.UserGeneratedAnswer.ugAnswerId)
                                >= setting_values['cap_template_qn_nonsense'],
                                func.sum(db.UserGeneratedAnswer.questionRating)
                                < 0))))

                ugAnswerQuery = aliased(db.UserGeneratedAnswer,
                                        ugAnswerQuery.subquery())
                ugQn = (Session.query(
                    db.UserGeneratedQuestion).outerjoin(ugAnswerQuery).filter(
                        ugAnswerQuery.ugQuestionGuid == None).filter(
                            db.UserGeneratedQuestion.questionId ==
                            dbQn.questionId).filter(
                                db.UserGeneratedQuestion.studentId !=
                                student.studentId).filter(
                                    db.UserGeneratedQuestion.superseded ==
                                    None).order_by(func.random()).first())
                if ugQn is not None:
                    # Found one, should return it
                    out = self.ugQuestionToJson(ugQn)
                else:
                    # Don't fall back to writing questions
                    raise BadRequest("No questions for student to review")
            else:
                # Author a question
                out = getQuestionDict(dbQn.plonePath)
                qnUri = self.request.getURL()
                if '?' in qnUri:
                    qnUri = qnUri.split('?')[0]
                out['uri'] = '%s?author_qn=yes' % self.request.getURL()
                if 'question_id' in self.request.form:
                    # Trying to rewrite a question, so add in what was written before
                    ugQn = (Session.query(db.UserGeneratedQuestion).filter(
                        db.UserGeneratedQuestion.ugQuestionGuid ==
                        self.request.form['question_id']).filter(
                            db.UserGeneratedQuestion.questionId ==
                            dbQn.questionId).filter(
                                db.UserGeneratedQuestion.studentId ==
                                student.studentId).filter(
                                    db.UserGeneratedQuestion.superseded ==
                                    None).first())
                    if ugQn is not None:
                        # Found one, add it to question
                        out['uri'] += '&question_id=%s' % ugQn.ugQuestionGuid
                        out['student_answer'] = dict(
                            text=ugQn.text,
                            choices=[
                                dict(
                                    answer=getattr(ugQn,
                                                   'choice_%d_answer' % i,
                                                   None),
                                    correct=getattr(ugQn,
                                                    'choice_%d_correct' % i,
                                                    None),
                                ) for i in range(0, 10)
                                if getattr(ugQn, 'choice_%d_correct' %
                                           i, None) is not None
                            ],
                            explanation=ugQn.explanation)
                    else:
                        raise NotFound(self, self.request.form['question_id'],
                                       self.request)

        # No custom techniques, fetch question @@data
        if not out:
            out = getQuestionDict(dbQn.plonePath)

        # Obsfucate answer
        if 'answer' in out:
            out['answer'] = base64.b64encode(json.dumps(out['answer']))
        return out
コード例 #26
0
ファイル: Resource.py プロジェクト: denishom12/decorator
    def COPY(self, REQUEST, RESPONSE):
        """Create a duplicate of the source resource whose state
        and behavior match that of the source resource as closely
        as possible. Though we may later try to make a copy appear
        seamless across namespaces (e.g. from Zope to Apache), COPY
        is currently only supported within the Zope namespace."""
        self.dav__init(REQUEST, RESPONSE)
        if not hasattr(aq_base(self), 'cb_isCopyable') or \
           not self.cb_isCopyable():
            raise MethodNotAllowed('This object may not be copied.')

        depth = REQUEST.get_header('Depth', 'infinity')
        if depth not in ('0', 'infinity'):
            raise BadRequest('Invalid Depth header.')

        dest = REQUEST.get_header('Destination', '')
        while dest and dest[-1] == '/':
            dest = dest[:-1]
        if not dest:
            raise BadRequest('Invalid Destination header.')

        try:
            path = REQUEST.physicalPathFromURL(dest)
        except ValueError:
            raise BadRequest('Invalid Destination header')

        name = path.pop()

        oflag = REQUEST.get_header('Overwrite', 'F').upper()
        if oflag not in ('T', 'F'):
            raise BadRequest('Invalid Overwrite header.')

        try:
            parent = self.restrictedTraverse(path)
        except ValueError:
            raise Conflict('Attempt to copy to an unknown namespace.')
        except NotFound:
            raise Conflict('Object ancestors must already exist.')
        except Exception:
            raise

        if hasattr(parent, '__null_resource__'):
            raise Conflict('Object ancestors must already exist.')
        existing = hasattr(aq_base(parent), name)
        if existing and oflag == 'F':
            raise PreconditionFailed('Destination resource exists.')
        try:
            parent._checkId(name, allow_dup=1)
        except Exception:
            raise Forbidden(sys.exc_info()[1])
        try:
            parent._verifyObjectPaste(self)
        except Unauthorized:
            raise
        except Exception:
            raise Forbidden(sys.exc_info()[1])

        # Now check locks.  The If header on a copy only cares about the
        # lock on the destination, so we need to check out the destinations
        # lock status.
        ifhdr = REQUEST.get_header('If', '')
        if existing:
            # The destination itself exists, so we need to check its locks
            destob = aq_base(parent)._getOb(name)
            if IWriteLock.providedBy(destob) and destob.wl_isLocked():
                if ifhdr:
                    itrue = destob.dav__simpleifhandler(
                        REQUEST, RESPONSE, 'COPY', refresh=1)
                    if not itrue:
                        raise PreconditionFailed()
                else:
                    raise Locked('Destination is locked.')
        elif IWriteLock.providedBy(parent) and parent.wl_isLocked():
            if ifhdr:
                parent.dav__simpleifhandler(REQUEST, RESPONSE, 'COPY',
                                            refresh=1)
            else:
                raise Locked('Destination is locked.')

        self._notifyOfCopyTo(parent, op=0)
        ob = self._getCopy(parent)
        ob._setId(name)

        if depth == '0' and isDavCollection(ob):
            for id in ob.objectIds():
                ob._delObject(id)

        notify(ObjectCopiedEvent(ob, self))

        if existing:
            object = getattr(parent, name)
            self.dav__validate(object, 'DELETE', REQUEST)
            parent._delObject(name)

        parent._setObject(name, ob)
        ob = parent._getOb(name)
        ob._postCopy(parent, op=0)

        compatibilityCall('manage_afterClone', ob, ob)

        notify(ObjectClonedEvent(ob))

        # We remove any locks from the copied object because webdav clients
        # don't track the lock status and the lock token for copied resources
        ob.wl_clearLocks()
        RESPONSE.setStatus(existing and 204 or 201)
        if not existing:
            RESPONSE.setHeader('Location', dest)
        RESPONSE.setBody('')
        return RESPONSE