Пример #1
0
def _process_permissions(schema, form, all_fields):
    # Get either read or write permissions depending on what type of
    # form this is
    permission_cache = {}  # permission name -> allowed/disallowed

    # name => permission name
    read_permissions = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)
    # name => permission name
    write_permissions = mergedTaggedValueDict(schema, WRITE_PERMISSIONS_KEY)
    security_manager = getSecurityManager()
    disallowed_fields = []

    for field_name, field_instance in all_fields.items():
        field_mode = field_instance.mode or form.mode
        permission_name = None
        base_name = _bn(field_instance)
        if field_mode == DISPLAY_MODE:
            permission_name = read_permissions.get(base_name, None)
        elif field_mode == INPUT_MODE:
            permission_name = write_permissions.get(base_name, None)
        if permission_name is None:
            continue
        if permission_name not in permission_cache:
            permission = queryUtility(IPermission, name=permission_name)
            if permission is None:
                permission_cache[permission_name] = True
            else:
                permission_cache[permission_name] = bool(
                    security_manager.checkPermission(permission.title,
                                                     form.context))
        if not permission_cache.get(permission_name, True):
            disallowed_fields.append(field_name)

    return all_fields.omit(*disallowed_fields)
Пример #2
0
 def _validate_vocabulary_name(self, schema, field, vocabulary_name):
     if not vocabulary_name:
         return True
     if (
         vocabulary_name != getattr(field, 'vocabulary', None) and
         vocabulary_name != getattr(field, 'vocabularyName', None)
     ):
         # Determine the widget to check for vocabulary there
         widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)
         widget = widgets.get(field.getName())
         if widget:
             if isinstance(widget, six.string_types):
                 widget = resolveDottedName(widget)
             if widget:
                 widget = widget(field, self._request)
         else:
             # default widget
             widget = queryMultiAdapter(
                 (field, self._request),
                 IFieldWidget
             )
         if widget:
             widget.update()
         if getattr(widget, 'vocabulary', None) != vocabulary_name:
             return False
     return True
Пример #3
0
    def validate(self, field_name, vocabulary_name=None):
        context = self.context
        checker = getSecurityManager().checkPermission
        schemata = self._get_schemata()
        for schema in schemata:
            if field_name not in schema:
                continue
            # If a vocabulary name was specified and it does not
            # match the vocabulary name for the field or widget,
            # fail.
            field = schema[field_name]
            if not self._validate_vocabulary_name(schema, field,
                                                  vocabulary_name):
                return False
            # Create mapping of all schema permissions
            permissions = mergedTaggedValueDict(schema, WRITE_PERMISSIONS_KEY)
            permission_name = permissions.get(field_name, None)
            if permission_name is not None:
                # if we have explicit permissions, check them
                permission = queryUtility(IPermission, name=permission_name)
                if permission:
                    return checker(permission.title, context)

            # If the field is in the schema, but no permission is
            # specified, fall back to the default edit permission
            return checker(self.DEFAULT_PERMISSION, context)
        else:
            raise AttributeError('No such field: {0}'.format(field_name))
Пример #4
0
    def __call__(self):
        result = {
            '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            '@id': self.context.absolute_url(),
            '@type': self.context.portal_type,
            'parent': {
                '@id': aq_parent(aq_inner(self.context)).absolute_url(),
                'title': aq_parent(aq_inner(self.context)).title,
                'description': aq_parent(aq_inner(self.context)).description
            },
            'created': json_compatible(self.context.created()),
            'modified': json_compatible(self.context.modified()),
            'UID': self.context.UID(),
        }

        for schema in iterSchemata(self.context):

            read_permissions = mergedTaggedValueDict(
                schema, READ_PERMISSIONS_KEY)

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

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

                serializer = queryMultiAdapter(
                    (field, self.context, self.request),
                    IFieldSerializer)
                value = serializer()
                result[json_compatible(name)] = value

        return result
Пример #5
0
def serializeToJSON(context, request):
    result = {}
    permission_cache = {}
    for schema in iterFlowSchemata(context):
        if not schema.providedBy(context):
            continue
        read_permissions = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)
        for name, field in getFields(schema).items():
            if IRichTextLabel.providedBy(field):
                continue
            if not check_permission(
                    read_permissions.get(name),
                    context,
                    permission_cache,
            ):
                continue

            serializer = queryMultiAdapter((field, context, request),
                                           IFieldSerializer)
            value = serializer()

            # Clean FlowSubmissionData values
            if value == removable:
                value = None
            elif isinstance(value, list):
                value = [v for v in value if v != removable]
            elif isinstance(value, tuple):
                value = tuple([v for v in value if v != removable])
            elif isinstance(value, set):
                value = set([v for v in value if v != removable])

            result[json_compatible(name)] = value
    return result
Пример #6
0
 def _validate_vocabulary_name(self, schema, field, vocabulary_name):
     if not vocabulary_name:
         return True
     if (
         vocabulary_name != getattr(field, 'vocabulary', None) and
         vocabulary_name != getattr(field, 'vocabularyName', None)
     ):
         # Determine the widget to check for vocabulary there
         widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)
         widget = widgets.get(field.getName())
         if widget:
             if isinstance(widget, six.string_types):
                 widget = resolveDottedName(widget)
             if widget:
                 widget = widget(field, self._request)
         else:
             # default widget
             widget = queryMultiAdapter(
                 (field, self._request),
                 IFieldWidget
             )
         if widget:
             widget.update()
         if getattr(widget, 'vocabulary', None) != vocabulary_name:
             return False
     return True
Пример #7
0
    def __call__(self):
        result = {
            '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            '@id': self.context.absolute_url(),
            '@type': self.context.portal_type,
            'parent': {
                '@id': aq_parent(aq_inner(self.context)).absolute_url(),
                'title': aq_parent(aq_inner(self.context)).title,
                'description': aq_parent(aq_inner(self.context)).description
            },
            'created': json_compatible(self.context.created()),
            'modified': json_compatible(self.context.modified()),
            'UID': self.context.UID(),
        }

        for schema in iterSchemata(self.context):

            read_permissions = mergedTaggedValueDict(schema,
                                                     READ_PERMISSIONS_KEY)

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

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

                serializer = queryMultiAdapter(
                    (field, self.context, self.request), IFieldSerializer)
                value = serializer()
                result[json_compatible(name)] = value

        return result
Пример #8
0
    def _include_fields(self, obj):
        """ """
        result = {}
        # Compute fields if include_all or metadata_fields
        if self.include_all or self.metadata_fields:
            for schema in iterSchemata(self.context):
                read_permissions = mergedTaggedValueDict(
                    schema, READ_PERMISSIONS_KEY)

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

                    # only keep relevant fields
                    if (self.include_all and not self.metadata_fields
                        ) or name in self.metadata_fields:

                        if not self.check_permission(
                                read_permissions.get(name), obj):
                            continue

                        # serialize the field
                        serializer = queryMultiAdapter(
                            (field, obj, self.request), IFieldSerializer)
                        value = serializer()
                        result[json_compatible(name)] = value

        return result
Пример #9
0
    def __call__(self):
        parent = aq_parent(aq_inner(self.context))
        parent_summary = getMultiAdapter(
            (parent, self.request), ISerializeToJsonSummary)()
        result = {
            # '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            '@id': self.context.absolute_url(),
            'id': self.context.id,
            '@type': self.context.portal_type,
            'parent': parent_summary,
            'created': json_compatible(self.context.created()),
            'modified': json_compatible(self.context.modified()),
            'review_state': self._get_workflow_state(),
            'UID': self.context.UID(),
        }

        for schema in iterSchemata(self.context):

            read_permissions = mergedTaggedValueDict(
                schema, READ_PERMISSIONS_KEY)

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

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

                serializer = queryMultiAdapter(
                    (field, self.context, self.request),
                    IFieldSerializer)
                value = serializer()
                result[json_compatible(name)] = value

        return result
Пример #10
0
    def test_mergedTaggedValueDict(self):
        class IBase1(Interface):
            pass

        class IBase2(Interface):
            pass

        class IBase3(Interface):
            pass

        class ISchema(IBase1, IBase2, IBase3):
            pass

        IBase1.setTaggedValue(u"foo", {
            1: 1,
            2: 1
        })  # more specific than IBase2 and IBase3
        IBase3.setTaggedValue(u"foo", {
            3: 3,
            2: 3,
            4: 3
        })  # least specific of the bases
        ISchema.setTaggedValue(u"foo", {4: 4, 5: 4})  # most specific

        self.assertEquals({
            1: 1,
            2: 1,
            3: 3,
            4: 4,
            5: 4
        }, utils.mergedTaggedValueDict(ISchema, u"foo"))
Пример #11
0
    def __call__(self):
        parent = aq_parent(aq_inner(self.context))
        parent_summary = getMultiAdapter(
            (parent, self.request), ISerializeToJsonSummary)()
        result = {
            # '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            '@id': self.context.absolute_url(),
            'id': self.context.id,
            '@type': self.context.portal_type,
            'parent': parent_summary,
            'created': json_compatible(self.context.created()),
            'modified': json_compatible(self.context.modified()),
            'review_state': self._get_workflow_state(),
            'UID': self.context.UID(),
        }

        for schema in iterSchemata(self.context):

            read_permissions = mergedTaggedValueDict(
                schema, READ_PERMISSIONS_KEY)

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

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

                serializer = queryMultiAdapter(
                    (field, self.context, self.request),
                    IFieldSerializer)
                value = serializer()
                result[json_compatible(name)] = value

        return result
Пример #12
0
    def __call__(self, version=None, include_items=True):
        version = "current" if version is None else version

        obj = self.getVersion(version)
        parent = aq_parent(aq_inner(obj))
        parent_summary = getMultiAdapter(
            (parent, self.request), ISerializeToJsonSummary
        )()
        result = {
            # '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            "@id": obj.absolute_url(),
            "id": obj.id,
            "@type": obj.portal_type,
            "parent": parent_summary,
            "created": json_compatible(obj.created()),
            "modified": json_compatible(obj.modified()),
            "review_state": self._get_workflow_state(obj),
            "UID": obj.UID(),
            "version": version,
            "layout": self.context.getLayout(),
            "is_folderish": False,
        }

        # Insert next/prev information
        nextprevious = NextPrevious(obj)
        result.update(
            {"previous_item": nextprevious.previous, "next_item": nextprevious.next}
        )

        # Insert expandable elements
        result.update(expandable_elements(self.context, self.request))

        # Insert field values
        for schema in iterSchemata(self.context):
            read_permissions = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)

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

                if not self.check_permission(read_permissions.get(name), obj):
                    continue

                # serialize the field
                serializer = queryMultiAdapter(
                    (field, obj, self.request), IFieldSerializer
                )
                value = serializer()
                result[json_compatible(name)] = value

        target_url = getMultiAdapter(
            (self.context, self.request), IObjectPrimaryFieldTarget
        )()
        if target_url:
            result["targetUrl"] = target_url

        result["allow_discussion"] = getMultiAdapter(
            (self.context, self.request), name="conversation_view"
        ).enabled()

        return result
Пример #13
0
 def isVisible(self):
     """Checks wheter the user has read permission of the field: if this is
     not the case, then the field is not displayed
     """
     return PermissionChecker(
         mergedTaggedValueDict(self.schema, READ_PERMISSIONS_KEY),
         self.context,
     ).allowed(self.field)
Пример #14
0
def all_merged_tagged_values_dict(ifaces, key):
    """mergedTaggedValueDict of all interfaces for a given key

    usally interfaces is a list of schemas
    """
    info = dict()
    for iface in ifaces:
        info.update(mergedTaggedValueDict(iface, key))
    return info
Пример #15
0
def all_merged_tagged_values_dict(ifaces, key):
    """mergedTaggedValueDict of all interfaces for a given key

    usally interfaces is a list of schemas
    """
    info = dict()
    for iface in ifaces:
        info.update(mergedTaggedValueDict(iface, key))
    return info
Пример #16
0
    def validate(self, field_name, vocabulary_name=None):
        context = self.context
        checker = getSecurityManager().checkPermission
        schemata = self._get_schemata()
        for schema in schemata:
            if field_name in schema:
                # If a vocabulary name was specified and it does not
                # match the vocabulary name for the field or widget,
                # fail.
                field = schema[field_name]
                if vocabulary_name and (
                        vocabulary_name != getattr(field, 'vocabulary', None)
                        and vocabulary_name != getattr(field, 'vocabularyName',
                                                       None)):
                    # Determine the widget to check for vocabulary there
                    widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)
                    widget = widgets.get(field_name)
                    if widget:
                        widget = (isinstance(widget, basestring)
                                  and resolveDottedName(widget) or widget)
                        widget = widget and widget(field, self._request)
                    else:
                        widget = queryMultiAdapter((field, self._request),
                                                   IFieldWidget)
                    if widget:
                        widget.update()
                    if getattr(widget, 'vocabulary', None) != vocabulary_name:
                        return False
                # Create mapping of all schema permissions
                permissions = mergedTaggedValueDict(schema,
                                                    WRITE_PERMISSIONS_KEY)
                permission_name = permissions.get(field_name, None)
                if permission_name is not None:
                    permission = queryUtility(IPermission,
                                              name=permission_name)
                    if permission:
                        return checker(permission.title, context)

                # If the field is in the schema, but no permission is
                # specified, fall back to the default edit permission
                return checker(self.DEFAULT_PERMISSION, context)
        else:
            raise AttributeError('No such field: {0}'.format(field_name))
Пример #17
0
 def updateWidgets(self):
     widgets = mergedTaggedValueDict(self.schema, WIDGETS_KEY)
     if self.field in widgets:
         factory = widgets[self.field]
         if self.fields[self.field].widgetFactory.get(
                     self.mode, None) is None:
             if isinstance(factory, basestring):
                 factory = resolveDottedName(factory)
             self.fields[self.field].widgetFactory = factory
     DisplayForm.updateWidgets(self)
Пример #18
0
def _process_permissions(schema, form, all_fields):
    # Get either read or write permissions depending on what type of
    # form this is
    permission_cache = {}  # permission name -> allowed/disallowed

    # name => permission name
    read_permissions = mergedTaggedValueDict(
        schema,
        READ_PERMISSIONS_KEY
    )
    # name => permission name
    write_permissions = mergedTaggedValueDict(
        schema,
        WRITE_PERMISSIONS_KEY
    )
    security_manager = getSecurityManager()
    disallowed_fields = []

    for field_name, field_instance in all_fields.items():
        field_mode = field_instance.mode or form.mode
        permission_name = None
        base_name = _bn(field_instance)
        if field_mode == DISPLAY_MODE:
            permission_name = read_permissions.get(base_name, None)
        elif field_mode == INPUT_MODE:
            permission_name = write_permissions.get(base_name, None)
        if permission_name is None:
            continue
        if permission_name not in permission_cache:
            permission = queryUtility(IPermission, name=permission_name)
            if permission is None:
                permission_cache[permission_name] = True
            else:
                permission_cache[permission_name] = bool(
                    security_manager.checkPermission(
                        permission.title,
                        form.context
                    )
                )
        if not permission_cache.get(permission_name, True):
            disallowed_fields.append(field_name)

    return all_fields.omit(*disallowed_fields)
Пример #19
0
def extractFieldInformation(schema, context, request, prefix):
    iro = [IEditForm, Interface]
    if prefix != '':
        prefix += '-'
    omitted = mergedTaggedValuesForIRO(schema, OMITTED_KEY, iro)
    modes = mergedTaggedValuesForIRO(schema, MODES_KEY, iro)
    widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)

    if context is not None:
        read_permissionchecker = PermissionChecker(
            mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY),
            context,
        )
        write_permissionchecker = PermissionChecker(
            mergedTaggedValueDict(schema, WRITE_PERMISSIONS_KEY),
            context,
        )

    read_only = []
    for name, mode in modes.items():
        if mode == HIDDEN_MODE:
            omitted[name] = True
        elif mode == DISPLAY_MODE:
            read_only.append(name)
    for name in schema.names(True):
        if context is not None:
            if not read_permissionchecker.allowed(name):
                omitted[name] = True
            if not write_permissionchecker.allowed(name):
                read_only.append(name)
        if isVisible(name, omitted):
            field = schema[name]
            if not IField.providedBy(field):
                continue
            if not IOmittedField.providedBy(field):
                yield {
                    'id': "%s.%s" % (schema.__identifier__, name),
                    'name': prefix + name,
                    'title': schema[name].title,
                    'widget': _getWidgetName(schema[name], widgets, request),
                    'readonly': name in read_only,
                }
Пример #20
0
def extractFieldInformation(schema, context, request, prefix):
    iro = [IEditForm, Interface]
    if prefix != '':
        prefix += '-'
    omitted = mergedTaggedValuesForIRO(schema, OMITTED_KEY, iro)
    modes = mergedTaggedValuesForIRO(schema, MODES_KEY, iro)
    widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)

    if context is not None:
        read_permissionchecker = PermissionChecker(
            mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY),
            context,
        )
        write_permissionchecker = PermissionChecker(
            mergedTaggedValueDict(schema, WRITE_PERMISSIONS_KEY),
            context,
        )

    read_only = []
    for name, mode in modes.items():
        if mode == HIDDEN_MODE:
            omitted[name] = True
        elif mode == DISPLAY_MODE:
            read_only.append(name)
    for name in schema.names(True):
        if context is not None:
            if not read_permissionchecker.allowed(name):
                omitted[name] = True
            if not write_permissionchecker.allowed(name):
                read_only.append(name)
        if isVisible(name, omitted):
            field = schema[name]
            if not IField.providedBy(field):
                continue
            if not IOmittedField.providedBy(field):
                yield {
                    'id': "%s.%s" % (schema.__identifier__, name),
                    'name': prefix + name,
                    'title': schema[name].title,
                    'widget': _getWidgetName(schema[name], widgets, request),
                    'readonly': name in read_only,
                }
Пример #21
0
    def validate(self, field_name, vocabulary_name=None):
        context = self.context
        checker = getSecurityManager().checkPermission
        schemata = self._get_schemata()
        for schema in schemata:
            if field_name in schema:
                # If a vocabulary name was specified and it does not
                # match the vocabulary name for the field or widget,
                # fail.
                field = schema[field_name]
                if vocabulary_name and (
                   vocabulary_name != getattr(field, 'vocabulary', None) and
                   vocabulary_name != getattr(field, 'vocabularyName', None)):
                    # Determine the widget to check for vocabulary there
                    widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)
                    widget = widgets.get(field_name)
                    if widget:
                        widget = (isinstance(widget, basestring) and
                                  resolveDottedName(widget) or widget)
                        widget = widget and widget(field, self._request)
                    else:
                        widget = queryMultiAdapter((field, self._request),
                                                   IFieldWidget)
                    if widget:
                        widget.update()
                    if getattr(widget, 'vocabulary', None) != vocabulary_name:
                        return False
                # Create mapping of all schema permissions
                permissions = mergedTaggedValueDict(schema,
                                                    WRITE_PERMISSIONS_KEY)
                permission_name = permissions.get(field_name, None)
                if permission_name is not None:
                    permission = queryUtility(IPermission,
                                              name=permission_name)
                    if permission:
                        return checker(permission.title, context)

                # If the field is in the schema, but no permission is
                # specified, fall back to the default edit permission
                return checker(self.DEFAULT_PERMISSION, context)
        else:
            raise AttributeError('No such field: {0}'.format(field_name))
    def check_permission(self, field_name):
        """Check field permission."""
        schema = self.get_field_schema(field_name)
        read_permissions = mergedTaggedValueDict(
            schema, READ_PERMISSIONS_KEY)
        permission = read_permissions.get(field_name)
        if permission is None:
            return True

        user = api.user.get_current()
        return api.user.has_permission(permission, user=user, obj=self.real_context)
    def check_permission(self, field_name):
        """Check field permission."""
        schema = self.get_field_schema(field_name)
        read_permissions = mergedTaggedValueDict(
            schema, READ_PERMISSIONS_KEY)
        permission = read_permissions.get(field_name)
        if permission is None:
            return True

        user = api.user.get_current()
        return api.user.has_permission(permission, user=user, obj=self.real_context)
Пример #24
0
def get_tagged_values(schemas, key):
    params = {}
    for schema in schemas:
        if not schema:
            continue
        tagged_values = mergedTaggedValueDict(schema, key)
        for field_name in schema:
            widget = tagged_values.get(field_name)
            if widget and widget.params:
                params[field_name] = widget.params
    return params
Пример #25
0
    def isVisible(self):
        """Checks wheter the user has read permission of the field: if this is
        not the case, then the field is not displayed
        """
        try:
            schema = next(self.additionalSchemata)
        except StopIteration:
            schema = self.schema

        return PermissionChecker(
            mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY),
            self.context,
        ).allowed(self.field)
Пример #26
0
    def isVisible(self):
        """Checks wheter the user has read permission of the field: if this is
        not the case, then the field is not displayed
        """
        try:
            schema = next(self.additionalSchemata)
        except StopIteration:
            schema = self.schema

        return PermissionChecker(
            mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY),
            self.context,
        ).allowed(self.field)
Пример #27
0
def get_tagged_values(schemas, key):
    params = {}
    for schema in schemas:
        if not schema:
            continue
        tagged_values = mergedTaggedValueDict(schema, key)
        for field_name in schema:
            widget = tagged_values.get(field_name)
            if IParameterizedWidget.providedBy(widget) and widget.params:
                params[field_name] = widget.params.copy()
                for k, v in params[field_name].items():
                    if callable(v):
                        params[field_name][k] = v()
    return params
Пример #28
0
def get_widget_params(schemas):
    params = {}
    for schema in schemas:
        if not schema:
            continue
        tagged_values = mergedTaggedValueDict(schema, WIDGETS_KEY)
        for field_name in schema:
            widget = tagged_values.get(field_name)
            if IParameterizedWidget.providedBy(widget) and widget.params:
                params[field_name] = {}
                for k, v in widget.params.items():
                    if callable(v):
                        v = v()
                    params[field_name][k] = v
    return params
Пример #29
0
    def canViewField(self, field):
        """returns True if the logged in user has permission to view this
        field
        """
        info = mergedTaggedValueDict(field.interface, READ_PERMISSIONS_KEY)

        # If there is no specific read permission, assume it is view
        if field not in info:
            return getSecurityManager().checkPermission(AccessControl.Permissions.view,
                                                        self)

        permission = queryUtility(IPermission, name=info[field])
        if permission is not None:
            return getSecurityManager().checkPermission(permission.title, self)

        return False
Пример #30
0
    def get_vocabulary(self):
        widget = self.context
        field = widget.field.bind(widget.context)

        # check field's write permission
        info = mergedTaggedValueDict(field.interface, WRITE_PERMISSIONS_KEY)
        permission_name = info.get(field.__name__, "cmf.ModifyPortalContent")
        permission = queryUtility(IPermission, name=permission_name)
        if permission is None:
            permission = getUtility(IPermission, name="cmf.ModifyPortalContent")
        if not getSecurityManager().checkPermission(permission.title, self.get_context()):
            raise VocabLookupException("Vocabulary lookup not allowed.")

        if ICollection.providedBy(field):
            return field.value_type.vocabulary
        else:
            return field.vocabulary
Пример #31
0
    def __call__(self, version=None, include_items=True):
        version = 'current' if version is None else version

        obj = self.getVersion(version)
        parent = aq_parent(aq_inner(obj))
        parent_summary = getMultiAdapter((parent, self.request),
                                         ISerializeToJsonSummary)()
        result = {
            # '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            '@id': obj.absolute_url(),
            'id': obj.id,
            '@type': obj.portal_type,
            'parent': parent_summary,
            'created': json_compatible(obj.created()),
            'modified': json_compatible(obj.modified()),
            'review_state': self._get_workflow_state(obj),
            'UID': obj.UID(),
            'version': version,
            'layout': self.context.getLayout(),
            'is_folderish': False
        }

        # Insert expandable elements
        result.update(expandable_elements(self.context, self.request))

        # Insert field values
        for schema in iterSchemata(self.context):

            read_permissions = mergedTaggedValueDict(schema,
                                                     READ_PERMISSIONS_KEY)

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

                if not self.check_permission(read_permissions.get(name), obj):
                    continue

                serializer = queryMultiAdapter((field, obj, self.request),
                                               IFieldSerializer)
                value = serializer()
                result[json_compatible(name)] = value

        result['allow_discussion'] = getMultiAdapter(
            (self.context, self.request), name='conversation_view').enabled()

        return result
Пример #32
0
    def test_mergedTaggedValueDict(self):
        class IBase1(Interface):
            pass

        class IBase2(Interface):
            pass

        class IBase3(Interface):
            pass

        class ISchema(IBase1, IBase2, IBase3):
            pass

        IBase1.setTaggedValue(u"foo", {1: 1, 2: 1})  # more specific than IBase2 and IBase3
        IBase3.setTaggedValue(u"foo", {3: 3, 2: 3, 4: 3})  # least specific of the bases
        ISchema.setTaggedValue(u"foo", {4: 4, 5: 4})  # most specific

        self.assertEqual({1: 1, 2: 1, 3: 3, 4: 4, 5: 4}, utils.mergedTaggedValueDict(ISchema, u"foo"))
Пример #33
0
    def get_vocabulary(self):
        widget = self.context
        field = widget.field.bind(widget.context)

        # check field's write permission
        info = mergedTaggedValueDict(field.interface, WRITE_PERMISSIONS_KEY)
        permission_name = info.get(field.__name__, 'cmf.ModifyPortalContent')
        permission = queryUtility(IPermission, name=permission_name)
        if permission is None:
            permission = getUtility(IPermission,
                                    name='cmf.ModifyPortalContent')
        if not getSecurityManager().checkPermission(permission.title,
                                                    self.get_context()):
            raise VocabLookupException('Vocabulary lookup not allowed.')

        if ICollection.providedBy(field):
            return field.value_type.vocabulary
        return field.vocabulary
Пример #34
0
    def __call__(self):
        primary_field_name = self.get_primary_field_name()
        for schema in iterSchemata(self.context):
            read_permissions = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)

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

                if not self.check_permission(read_permissions.get(name), self.context):
                    continue

                if name != primary_field_name:
                    continue

                target_adapter = queryMultiAdapter(
                    (field, self.context, self.request), IPrimaryFieldTarget
                )
                if target_adapter:
                    target = target_adapter()
                    if target:
                        return target
def get_fields_in_order_with_permission(schema, context):
    checker = getSecurityManager().checkPermission
    permissions = mergedTaggedValueDict(
        schema,
        READ_PERMISSIONS_KEY
    )

    result = []
    for field in getFieldsInOrder(schema):
        permission_name = permissions.get(field[0], None)
        if permission_name is not None:
            permission = queryUtility(IPermission,
                                      name=permission_name)
            if permission:
                if not checker(permission.title, context):
                    # Ignore this field
                    continue

        result.append(field)

    return result
Пример #36
0
 def __call__(self, name, value):
     
     # Short circuit for things like views or viewlets
     if name == '':
         return 1
     
     context = aq_parent(self)
     
     schema = self._get_schema(context)
     if schema is None:
         return 1
     
     info = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)
     
     if name not in info:
         return 1
     
     permission = queryUtility(IPermission, name=info[name])
     if permission is not None:
         return getSecurityManager().checkPermission(permission.title, context)
     
     return 0
Пример #37
0
    def __call__(self, name, value):

        # Short circuit for things like views or viewlets
        if name == '':
            return 1

        context = aq_parent(self)

        schema = self._get_schema(context)
        if schema is None:
            return 1

        info = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)

        if name not in info:
            return 1

        permission = queryUtility(IPermission, name=info[name])
        if permission is not None:
            return getSecurityManager().checkPermission(permission.title, context)

        return 0
Пример #38
0
    def validate(self, field_name, vocabulary_name=None):
        context = self.context
        checker = getSecurityManager().checkPermission
        schemata = self._get_schemata()
        for schema in schemata:
            if field_name not in schema:
                continue
            # If a vocabulary name was specified and it does not
            # match the vocabulary name for the field or widget,
            # fail.
            field = schema[field_name]
            if not self._validate_vocabulary_name(
                schema,
                field,
                vocabulary_name
            ):
                return False
            # Create mapping of all schema permissions
            permissions = mergedTaggedValueDict(
                schema,
                WRITE_PERMISSIONS_KEY
            )
            permission_name = permissions.get(field_name, None)
            if permission_name is not None:
                # if we have explicit permissions, check them
                permission = queryUtility(
                    IPermission,
                    name=permission_name
                )
                if permission:
                    return checker(permission.title, context)

            # If the field is in the schema, but no permission is
            # specified, fall back to the default edit permission
            return checker(self.DEFAULT_PERMISSION, context)
        else:
            raise AttributeError('No such field: {0}'.format(field_name))
Пример #39
0
    def __call__(self):
        parent = self.context.__parent__
        if parent is not None:
            try:
                parent_summary = getMultiAdapter((parent, self.request),
                                                 ISerializeToJsonSummary)()
            except ComponentLookupError:
                parent_summary = {}
        else:
            parent_summary = {}

        result = {
            '@id': '/'.join(get_physical_path(self.context)),
            'id': self.context.id,
            '@type': self.context.portal_type,
            'parent': parent_summary,
            'created': json_compatible(self.context.creation_date),
            'modified': json_compatible(self.context.modification_date),
            'UID': self.context.UID(),
        }

        for schema in iterSchemata(self.context):

            read_permissions = mergedTaggedValueDict(schema,
                                                     READ_PERMISSIONS_KEY)

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

                if not self.check_permission(read_permissions.get(name)):
                    continue
                serializer = queryMultiAdapter(
                    (field, self.context, self.request), IFieldSerializer)
                value = serializer()
                result[json_compatible(name)] = value

        return result
Пример #40
0
    def __call__(self, validate_all=False):
        data = json_body(self.request)

        modified = False
        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

                    # 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': e.message, '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)
                            modified = True

                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': error.message})

        if errors:
            raise BadRequest(errors)

        if modified:
            notify(ObjectModifiedEvent(self.context))

        return self.context
Пример #41
0
    def __call__(self, validate_all=False, data=None):  # 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': e.message,
                            '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': error.message})

        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:
            descriptions = []
            for interface, names in modified.items():
                descriptions.append(Attributes(interface, *names))
            notify(ObjectModifiedEvent(self.context, *descriptions))

        return self.context
Пример #42
0
def _process_fieldsets(form, schema, groups, all_fields, prefix,
                       default_group):
    """ Keep track of which fields are in a fieldset, and, by elimination,
    which ones are not
    """
    # { name => e.g. 'hidden' }
    modes = mergedTaggedValuesForForm(schema, MODES_KEY, form)

    # { name => widget/dotted name }
    widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)

    # list of IFieldset instances
    fieldsets = mergedTaggedValueList(schema, FIELDSETS_KEY)

    # process primary schema fieldsets
    fieldset_fields = []
    for fieldset in fieldsets:
        for field_name in fieldset.fields:
            fieldset_fields.append(_process_prefixed_name(prefix, field_name))

    # Set up the default fields, widget factories and widget modes
    new_fields = all_fields.omit(*fieldset_fields)
    _process_widgets(form, widgets, modes, new_fields)

    if not default_group:
        form.fields += new_fields
    else:
        groups[default_group].fields += new_fields

    # Set up fields for fieldsets

    for fieldset in fieldsets:
        new_fields = all_fields.select(*[
            _process_prefixed_name(prefix, name) for name in fieldset.fields
            if _process_prefixed_name(prefix, name) in all_fields
        ])

        if fieldset.__name__ in groups:
            # Process also, if no fields are defined to allow fieldset-only
            # configurations via plone.supermodel fieldset directive.
            group = groups[fieldset.__name__]
            group.fields += new_fields
            if (fieldset.label and group.label != fieldset.label
                    and group.__name__ != fieldset.label  # defaults to name!
                ):
                group.label = fieldset.label
            if (fieldset.description
                    and group.description != fieldset.description):
                group.description = fieldset.description
            if (fieldset.order and fieldset.order != DEFAULT_ORDER
                    and fieldset.order != group.order):
                group.order = fieldset.order

        if len(new_fields) > 0 or getattr(form, 'showEmptyGroups', False):
            _process_widgets(form, widgets, modes, new_fields)
            if fieldset.__name__ not in groups:
                group = GroupFactory(fieldset.__name__,
                                     label=fieldset.label,
                                     description=fieldset.description,
                                     order=fieldset.order,
                                     fields=new_fields)
                form.groups.append(group)
                groups[group.__name__] = group
Пример #43
0
    def __call__(self, validate_all=False):
        data = json_body(self.request)

        modified = False
        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

                    # 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': e.message,
                            '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)
                            modified = True

                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': error.message})

        if errors:
            raise BadRequest(errors)

        if modified:
            notify(ObjectModifiedEvent(self.context))

        return self.context
Пример #44
0
def processFields(form, schema, prefix='', defaultGroup=None, permissionChecks=True):
    """Add the fields from the schema to the form, taking into account
    the hints in the various tagged values as well as fieldsets. If prefix
    is given, the fields will be prefixed with this prefix. If 
    defaultGroup is given (as a Fieldset instance), any field not explicitly
    placed into a particular fieldset, will be added to the given group,
    which must exist already. If permissionChecks is false,
    permission checks are ignored.
    """

    # Get data from tagged values, flattening data from super-interfaces
    
    # Note: The names always refer to a field in the schema, and never contain a prefix.
    
    omitted   = mergedTaggedValuesForForm(schema, OMITTED_KEY, form)   # { name => True }
    modes     = mergedTaggedValuesForForm(schema, MODES_KEY, form)     # { name => e.g. 'hidden' }
    widgets   = mergedTaggedValueDict(schema, WIDGETS_KEY)             # { name => widget/dotted name }
    
    fieldsets = mergedTaggedValueList(schema, FIELDSETS_KEY)           # list of IFieldset instances
    
    # Get either read or write permissions depending on what type of form this is
    
    readPermissions  = {}  # field name -> permission name
    writePermissions = {}  # field name -> permission name
    permissionCache  = {}  # permission name -> allowed/disallowed
    
    if permissionChecks:
        readPermissions  = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)  # name => permission name
        writePermissions = mergedTaggedValueDict(schema, WRITE_PERMISSIONS_KEY) # name => permission name
        securityManager  = getSecurityManager()
        
    # Find the fields we should not worry about
    
    groups = {}
    doNotProcess = list(form.fields.keys())

    for fieldName, status in omitted.items():
        if status and status != 'false':
            doNotProcess.append(_fn(prefix, fieldName))
    
    for group in form.groups:
        doNotProcess.extend(list(group.fields.keys()))
        
        groupName = getattr(group, '__name__', group.label)
        groups[groupName] = group

    # Find all allowed fields so that we have something to select from
    omitReadOnly = form.mode != DISPLAY_MODE
    allFields = field.Fields(schema, prefix=prefix, omitReadOnly=omitReadOnly).omit(*doNotProcess)
    
    # Check permissions
    if permissionChecks:
        
        disallowedFields = []
        
        for fieldName, fieldInstance in allFields.items():
            fieldName = fieldInstance.__name__
            fieldMode = fieldInstance.mode or form.mode
            
            permissionName = None
            if fieldMode == DISPLAY_MODE:
                permissionName = readPermissions.get(_bn(fieldInstance), None)
            elif fieldMode == INPUT_MODE:
                permissionName = writePermissions.get(_bn(fieldInstance), None)
            if permissionName is not None:
                if permissionName not in permissionCache:
                    permission = queryUtility(IPermission, name=permissionName)
                    if permission is None:
                        permissionCache[permissionName] = True
                    else:
                        permissionCache[permissionName] = bool(securityManager.checkPermission(permission.title, form.context))
                if not permissionCache.get(permissionName, True):
                    disallowedFields.append(fieldName)
        
        allFields = allFields.omit(*disallowedFields)
    
    # Keep track of which fields are in a fieldset, and, by elimination,
    # which ones are not 
    
    fieldsetFields = []
    for fieldset in fieldsets:
        for fieldName in fieldset.fields:
            fieldsetFields.append(_fn(prefix, fieldName))
    
    # Set up the default fields, widget factories and widget modes
    
    newFields = allFields.omit(*fieldsetFields)
    _processWidgets(form, widgets, modes, newFields)
    
    if not defaultGroup:
        form.fields += newFields
    else:
        groups[defaultGroup].fields += newFields
    
    # Set up fields for fieldsets
    
    for fieldset in fieldsets:
        
        newFields = allFields.select(*[_fn(prefix, fieldName) 
                                            for fieldName in fieldset.fields
                                                if _fn(prefix, fieldName) in allFields])
        
        if len(newFields) > 0:        
            _processWidgets(form, widgets, modes, newFields)
        
            if fieldset.__name__ not in groups:
                form.groups.append(GroupFactory(fieldset.__name__,
                                                label=fieldset.label,
                                                description=fieldset.description,
                                                fields=newFields))
            else:
                groups[fieldset.__name__].fields += newFields
Пример #45
0
def processFields(form, schema, prefix='', defaultGroup=None,
                  permissionChecks=True):
    """Add the fields from the schema to the form, taking into account
    the hints in the various tagged values as well as fieldsets. If prefix
    is given, the fields will be prefixed with this prefix. If
    defaultGroup is given (as a Fieldset instance), any field not explicitly
    placed into a particular fieldset, will be added to the given group,
    which must exist already. If permissionChecks is false,
    permission checks are ignored.
    """

    # Get data from tagged values, flattening data from super-interfaces

    # Note: The names always refer to a field in the schema, and never
    # contain a prefix.

    # { name => True }
    omitted = mergedTaggedValuesForForm(schema, OMITTED_KEY, form)

    # { name => e.g. 'hidden' }
    modes = mergedTaggedValuesForForm(schema, MODES_KEY, form)

    # { name => widget/dotted name }
    widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)

    # list of IFieldset instances
    fieldsets = mergedTaggedValueList(schema, FIELDSETS_KEY)

    # Get either read or write permissions depending on what type of
    # form this is
    readPermissions = {}  # field name -> permission name
    writePermissions = {}  # field name -> permission name
    permissionCache = {}  # permission name -> allowed/disallowed

    if permissionChecks:
        # name => permission name
        readPermissions = mergedTaggedValueDict(
            schema,
            READ_PERMISSIONS_KEY
        )
        # name => permission name
        writePermissions = mergedTaggedValueDict(
            schema,
            WRITE_PERMISSIONS_KEY
        )
        securityManager = getSecurityManager()

    # Find the fields we should not worry about

    groups = {}
    doNotProcess = list(form.fields.keys())

    for fieldName, status in omitted.items():
        if status and status != 'false':
            doNotProcess.append(_fn(prefix, fieldName))

    for group in form.groups:
        doNotProcess.extend(list(group.fields.keys()))

        groupName = getattr(group, '__name__', group.label)
        groups[groupName] = group

    # Find all allowed fields so that we have something to select from
    omitReadOnly = form.mode != DISPLAY_MODE
    allFields = field.Fields(
        schema,
        prefix=prefix,
        omitReadOnly=omitReadOnly
    ).omit(*doNotProcess)

    # Check permissions
    if permissionChecks:

        disallowedFields = []

        for fieldName, fieldInstance in allFields.items():
            fieldName = fieldInstance.__name__
            fieldMode = fieldInstance.mode or form.mode

            permissionName = None
            if fieldMode == DISPLAY_MODE:
                permissionName = readPermissions.get(_bn(fieldInstance), None)
            elif fieldMode == INPUT_MODE:
                permissionName = writePermissions.get(_bn(fieldInstance), None)
            if permissionName is not None:
                if permissionName not in permissionCache:
                    permission = queryUtility(IPermission, name=permissionName)
                    if permission is None:
                        permissionCache[permissionName] = True
                    else:
                        permissionCache[permissionName] = bool(
                            securityManager.checkPermission(
                                permission.title,
                                form.context
                            )
                        )
                if not permissionCache.get(permissionName, True):
                    disallowedFields.append(fieldName)

        allFields = allFields.omit(*disallowedFields)

    # Keep track of which fields are in a fieldset, and, by elimination,
    # which ones are not

    fieldsetFields = []
    for fieldset in fieldsets:
        for fieldName in fieldset.fields:
            fieldsetFields.append(_fn(prefix, fieldName))

    # Set up the default fields, widget factories and widget modes

    newFields = allFields.omit(*fieldsetFields)
    _processWidgets(form, widgets, modes, newFields)

    if not defaultGroup:
        form.fields += newFields
    else:
        groups[defaultGroup].fields += newFields

    # Set up fields for fieldsets

    for fieldset in fieldsets:

        newFields = allFields.select(*[_fn(prefix, fieldName)
                                       for fieldName in fieldset.fields
                                       if _fn(prefix, fieldName) in allFields])

        if getattr(form, 'showEmptyGroups', False) or (len(newFields) > 0):
            _processWidgets(form, widgets, modes, newFields)

            if fieldset.__name__ not in groups:
                group = GroupFactory(fieldset.__name__,
                                     label=fieldset.label,
                                     description=fieldset.description,
                                     fields=newFields)
                form.groups.append(group)
                groups[group.__name__] = group
            else:
                groups[fieldset.__name__].fields += newFields
Пример #46
0
    def __call__(self, validate_all=False):  # noqa: ignore=C901
        data = json_body(self.request)

        modified = False
        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

                    # 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': e.message,
                            'field': name,
                            'error': e
                        })
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(),
                            'field': name,
                            'error': e
                        })
                    else:
                        field_data[name] = value

                        if IDatetime.providedBy(dm.field):
                            # Do not compare both, just set the value. See
                            # https://github.com/plone/plone.restapi/issues/253
                            dm.set(value)
                            modified = True
                        else:
                            if value != dm.get():
                                dm.set(value)
                                modified = True

                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': error.message})

        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:
            notify(ObjectModifiedEvent(self.context))

        return self.context
Пример #47
0
    def __call__(self, data, validate_all=False):

        modified = False
        errors = []

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

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

                if field.readonly:
                    continue

                if name in data:

                    if not self.check_permission(write_permissions.get(name)):
                        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': e.message, 'field': name, 'error': e})
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(), 'field': name, 'error': e})
                    else:
                        f = schema.get(name)
                        try:
                            f.validate(value)
                        except ValidationError as e:
                            errors.append({
                                'message': e.doc(), 'field': name, 'error': e})
                        else:
                            setattr(schema(self.context), name, value)

            if validate_all:
                validation = getValidationErrors(schema, schema(self.context))

                if len(validation):
                    for e in validation:
                        errors.append({
                            'message': e[1].doc(),
                            'field': e[0],
                            'error': e
                            })
        if errors:
            raise DeserializationError(errors)

        if modified:
            notify(ObjectModifiedEvent(self.context))

        return self.context
Пример #48
0
    def __call__(self, version=None):
        version = "current" if version is None else version
        if version != "current":
            return {}

        query = self._build_query()

        catalog = getToolByName(self.context, "portal_catalog")
        brains = catalog(query)

        batch = HypermediaBatch(self.request, brains)

        result = {
            # '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            "@id": self.context.absolute_url(),
            "id": self.context.id,
            "@type": "Plone Site",
            "title": self.context.Title(),
            "parent": {},
            "is_folderish": True,
            "description": self.context.description,
        }

        if HAS_PLONE_6:
            # Insert Plone Site DX root field values
            for schema in iterSchemata(self.context):
                read_permissions = mergedTaggedValueDict(
                    schema, READ_PERMISSIONS_KEY)

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

                    if not self.check_permission(read_permissions.get(name),
                                                 self.context):
                        continue

                    # serialize the field
                    serializer = queryMultiAdapter(
                        (field, self.context, self.request), IFieldSerializer)
                    value = serializer()
                    result[json_compatible(name)] = value

            # Insert locking information
            result.update({"lock": lock_info(self.context)})
        else:
            # Apply the fake blocks behavior in site root hack using site root properties
            result.update({
                "blocks":
                self.serialize_blocks(),
                "blocks_layout":
                json.loads(getattr(self.context, "blocks_layout", "{}")),
            })

        # Insert expandable elements
        result.update(expandable_elements(self.context, self.request))

        result["items_total"] = batch.items_total
        if batch.links:
            result["batching"] = batch.links

        result["items"] = [
            getMultiAdapter((brain, self.request), ISerializeToJsonSummary)()
            for brain in batch
        ]

        return result
Пример #49
0
    def get_schema_data(self, data, validate_all):
        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:
                            if dm.get():
                                self.mark_field_as_changed(schema, name)
                            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)
                            self.mark_field_as_changed(schema, 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
                        })

        return schema_data, errors
Пример #50
0
def _process_fieldsets(
    form,
    schema,
    groups,
    all_fields,
    prefix,
    default_group
):
    """ Keep track of which fields are in a fieldset, and, by elimination,
    which ones are not
    """
    # { name => e.g. 'hidden' }
    modes = mergedTaggedValuesForForm(schema, MODES_KEY, form)

    # { name => widget/dotted name }
    widgets = mergedTaggedValueDict(schema, WIDGETS_KEY)

    # list of IFieldset instances
    fieldsets = mergedTaggedValueList(schema, FIELDSETS_KEY)

    # process primary schema fieldsets
    fieldset_fields = []
    for fieldset in fieldsets:
        for field_name in fieldset.fields:
            fieldset_fields.append(_process_prefixed_name(prefix, field_name))

    # Set up the default fields, widget factories and widget modes
    new_fields = all_fields.omit(*fieldset_fields)
    _process_widgets(form, widgets, modes, new_fields)

    if not default_group:
        form.fields += new_fields
    else:
        groups[default_group].fields += new_fields

    # Set up fields for fieldsets

    for fieldset in fieldsets:
        new_fields = all_fields.select(
            *[_process_prefixed_name(prefix, name) for name in fieldset.fields
              if _process_prefixed_name(prefix, name) in all_fields]
        )

        if fieldset.__name__ in groups:
            # Process also, if no fields are defined to allow fieldset-only
            # configurations via plone.supermodel fieldset directive.
            group = groups[fieldset.__name__]
            group.fields += new_fields
            if (
                fieldset.label and
                group.label != fieldset.label and
                group.__name__ != fieldset.label  # defaults to name!
            ):
                group.label = fieldset.label
            if (
                fieldset.description and
                group.description != fieldset.description
            ):
                group.description = fieldset.description
            if (
                fieldset.order and
                fieldset.order != DEFAULT_ORDER and
                fieldset.order != group.order
            ):
                group.order = fieldset.order

        if len(new_fields) > 0 or getattr(form, 'showEmptyGroups', False):
            _process_widgets(form, widgets, modes, new_fields)
            if fieldset.__name__ not in groups:
                group = GroupFactory(fieldset.__name__,
                                     label=fieldset.label,
                                     description=fieldset.description,
                                     order=fieldset.order,
                                     fields=new_fields)
                form.groups.append(group)
                groups[group.__name__] = group