Beispiel #1
0
def _add_arbitrary_filter_node(name, index: SDIndex, schema):
    int_index = False
    if 'unique_values' in index.__dir__():
        indexed_values = index.unique_values()
        if indexed_values and isinstance(indexed_values[0], int):
            int_index = True
    node = Integer(name=name) if int_index else SingleLine(name=name)
    node = node.bind(**schema.bindings)
    schema.add(node)
Beispiel #2
0
class RateSchema(colander.MappingSchema):
    """Rate sheet data structure."""

    subject = ReferenceSchema(reftype=RateSubjectReference)
    object = ReferenceSchema(reftype=RateObjectReference)
    rate = Integer()

    def validator(self, node, value):
        """
        Validate the rate.

        1. Validate that the subject is the user who is currently logged-in.

        2. Ensure that no other rate for the same subject/object combination
           exists, except predecessors of this version.

        3. Ask the validator registered for *object* whether *rate* is valid.
           In this way, `IRateable` subclasses can modify the range of allowed
           ratings by registering their own `IRateValidator` adapter.
        """
        # TODO make this validator deferred
        # TODO add post_pool validator
        request = node.bindings['request']
        self._validate_subject_is_current_user(node, value, request)
        self._ensure_rate_is_unique(node, value, request)
        self._query_registered_object_validator(node, value, request)

    def _validate_subject_is_current_user(self, node, value, request):
        user = get_user(request)
        if user is None or user != value['subject']:
            err = colander.Invalid(node)
            err['subject'] = 'Must be the currently logged-in user'
            raise err

    def _ensure_rate_is_unique(self, node, value, request):
        # Other rates with the same subject and object may occur below the
        # current context (earlier versions of the same rate item).
        # If they occur elsewhere, an error is thrown.
        adhocracy_catalog = find_catalog(request.context, 'adhocracy')
        index = adhocracy_catalog['reference']
        reference_subject = Reference(None, IRate, 'subject', value['subject'])
        query = index.eq(reference_subject)
        reference_object = Reference(None, IRate, 'object', value['object'])
        query &= index.eq(reference_object)
        system_catalog = find_catalog(request.context, 'system')
        path_index = system_catalog['path']
        query &= path_index.noteq(resource_path(request.context), depth=None)
        elements = query.execute(resolver=None)
        if elements:
            err = colander.Invalid(node)
            err['object'] = 'Another rate by the same user already exists'
            raise err

    def _query_registered_object_validator(self, node, value, request):
        registry = request.registry
        rate_validator = registry.getAdapter(value['object'], IRateValidator)
        if not rate_validator.validate(value['rate']):
            err = colander.Invalid(node)
            err['rate'] = rate_validator.helpful_error_message()
            raise err
Beispiel #3
0
class AssetMetadataSchema(MappingSchema):
    """Data structure storing asset metadata."""

    mime_type = SingleLine(readonly=True)
    size = Integer(readonly=True)
    filename = SingleLine(readonly=True)
    attached_to = UniqueReferences(readonly=True,
                                   backref=True,
                                   reftype=AssetReference)
Beispiel #4
0
class CommentableSchema(MappingSchema):
    """Commentable sheet data structure.

    `post_pool`: Pool to post new :class:`adhocracy_sample.resource.IComment`.
    """

    comments_count = Integer(readonly=True,
                             default=deferred_default_comment_count)
    post_pool = PostPool(iresource_or_service_name='comments')
Beispiel #5
0
 def _add_additional_nodes(self, schema: MappingSchema, params: dict):
     if params.get('serialization_form', False) == 'content':
         elements = schema['elements']
         typ_copy = deepcopy(elements.children[0].typ)
         typ_copy.serialization_form = 'content'
         elements.children[0].typ = typ_copy
     if params.get('show_count', True):  # pragma: no branch
         child = Integer(default=0, missing=drop, name='count')
         schema.add(child)
     if params.get('show_frequency', False):
         child = SchemaNode(MappingType(unknown='preserve'),
                            default={},
                            missing=drop,
                            name='aggregateby')
         schema.add(child)
     return schema
Beispiel #6
0
class RateSchema(MappingSchema):
    """Rate sheet data structure."""

    subject = ReferenceSchema(reftype=RateSubjectReference)
    object = ReferenceSchema(reftype=RateObjectReference)
    rate = Integer()

    preparer = deferred_anonymize_rate_subject

    @deferred
    def validator(self, kw: dict) -> callable:
        """Validate the rate."""
        # TODO add post_pool validator
        context = kw['context']
        request = kw['request']
        registry = kw['registry']
        return All(
            create_validate_rate_value(registry),
            create_validate_subject(request),
            create_validate_is_unique(context, request),
        )
Beispiel #7
0
 def make_one(self):
     from adhocracy_core.schema import Integer
     return Integer()
Beispiel #8
0
def create_arbitrary_filter_node(index, example_value, query):
    return Integer()
Beispiel #9
0
class GETPoolRequestSchema(MappingSchema):
    """GET parameters accepted for pool queries."""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Raise if unknown to tell client the query parameters are wrong.
        self.typ.unknown = 'raise'

    # TODO For now we don't have a way to specify GET parameters that can
    # be repeated, e.g. 'sheet=Blah&sheet=Blub'. The querystring is converted
    # by Cornice into a MultiDict (http://docs.pylonsproject.org/projects
    # /pyramid/en/master/api/interfaces.html#pyramid.interfaces.IMultiDict),
    # which by default will only return the LAST value if a key is specified
    # several times. One possible workaround is to allow specifying multiple
    # values as a comma-separated list instead of repeated key=value pairs,
    # e.g. 'sheet=Blah,Blub'. This would require a custom Multiple SchemaNode
    # that wraps a SchemaType, e.g.
    # sheet = Multiple(Interface(), missing=None, sep=',')
    # Elements in this schema were multiple values should be allowed:
    # sheet, aggregateby, tag.

    depth = PoolQueryDepth()
    elements = PoolElementsForm(missing=drop)
    count = Boolean(missing=drop)
    sort = SingleLine(missing=drop, validator=deferred_validate_sort)
    reverse = Boolean(missing=drop)
    # TODO: validate limit, offset to be multiple of 10, 20, 50, 100, 200, 500
    limit = Integer(missing=drop)
    offset = Integer(missing=drop)
    aggregateby = SingleLine(missing=drop,
                             validator=deferred_validate_aggregateby)

    def deserialize(self, cstruct=null):  # noqa
        """Deserialize the :term:`cstruct` into an :term:`appstruct`.

        Adapt key/values to :class:`adhocracy_core.interfaces.SearchQuery`. for
        BBB.

        TODO: Change API according to internal SearchQuery api.
        refactor to follow coding guideline better.
        """
        depth_cstruct = cstruct.get('depth', None)
        if depth_cstruct == 'all':
            cstruct['depth'] = 100
        appstruct = super().deserialize(cstruct)
        search_query = {}
        if appstruct:  # pragma: no branch
            search_query['root'] = self.bindings['context']
        if 'depth' in appstruct:  # pragma: no branch
            depth = appstruct['depth']
            if depth == 100:
                depth = None
            search_query['depth'] = depth
        if 'elements' in appstruct:
            elements = appstruct.get('elements')
            search_query['serialization_form'] = elements
            if elements == 'omit':
                search_query['resolve'] = False
        interfaces = ()
        if 'sheet' in appstruct:
            interfaces = appstruct['sheet']
        if interfaces:
            search_query['interfaces'] = interfaces
        if 'aggregateby' in appstruct:
            search_query['frequency_of'] = appstruct['aggregateby']
            search_query['show_frequency'] = True
        if 'sort' in appstruct:
            search_query['sort_by'] = appstruct['sort']
        if 'limit' in appstruct:
            search_query['limit'] = appstruct['limit']
        if 'offset' in appstruct:
            search_query['offset'] = appstruct['offset']
        if 'reverse' in appstruct:
            search_query['reverse'] = appstruct['reverse']
        if 'count' in appstruct:
            search_query['show_count'] = appstruct['count']
        fields = tuple([x.name for x in GETPoolRequestSchema().children])
        fields += ('sheet', )
        for filter, query in appstruct.items():
            if filter in fields + SearchQuery._fields:
                continue
            if ':' in filter:
                if 'references' not in search_query:  # pragma: no branch
                    search_query['references'] = []
                isheet_name, isheet_field = filter.split(':')
                isheet = resolver.resolve(isheet_name)
                target = appstruct[filter]
                reference = ReferenceTuple(None, isheet, isheet_field, target)
                search_query['references'].append(reference)
            else:
                if 'indexes' not in search_query:
                    search_query['indexes'] = {}
                if filter == 'content_type':
                    search_query['indexes']['interfaces'] = appstruct[
                        'content_type']
                    continue
                search_query['indexes'][filter] = query
        return search_query
Beispiel #10
0
class FieldComparableInteger(FieldComparableBase):
    """Tuple with values FieldComparable and Integer."""

    value = Integer()
Beispiel #11
0
class KeywordComparableInteger(KeywordComparableBase):
    """Tuple with values KeywordComparable and Integer."""

    value = Integer()
Beispiel #12
0
class WinnerInfoSchema(MappingSchema):
    funding = Integer()
Beispiel #13
0
class DurationSchema(MappingSchema):
    duration = Integer(missing=required)
Beispiel #14
0
class ServiceKontoSchema(MappingSchema):
    """Data structure for ServiceKonto user information."""

    userid = Integer()