Example #1
0
def user_category_filter(queryset, user):
    """
    Returns Queryset containing only user's prefered content (filtering based on categories).
    If queryset.model has no relation to ella.core.models.Category, original queryset is returned.
    """
    from newman.permission import model_category_fk, is_category_model

    qs = queryset
    category_fk = model_category_fk(qs.model)
    if not category_fk:
        return qs
    root_category_ids = get_user_config(user, newman_settings.CATEGORY_FILTER)
    if not root_category_ids:  # user has no custom category filter set or his filter set is empty.
        return qs
    if not user.is_superuser:
        helper = models.DenormalizedCategoryUserRole.objects.filter(
            user_id=user.pk, root_category_id__in=root_category_ids
        ).values("category_id")
        user_categories = [c["category_id"] for c in helper]
        if is_category_model(qs.model):
            lookup = "id__in"
        else:
            lookup = "%s__in" % category_fk.name
        out = qs.filter(**{lookup: user_categories})
    else:
        cats = Category.objects.filter(pk__in=root_category_ids).values("site__pk")
        user_sites = [c["site__pk"] for c in cats]
        if is_category_model(qs.model):
            lookup = "site__id__in"
        else:
            lookup = "%s__site__id__in" % category_fk.name
        out = qs.filter(**{lookup: user_sites})
    flag_queryset(out, "user_category_filtered", True)
    return out
Example #2
0
    def full_clean(self):
        super(BaseGenericInlineFormSet, self).full_clean()
        cfield = model_category_fk(self.instance)
        if not cfield:
            return
        #cat = model_category_fk_value(self.instance)

        # next part is category-based permissions (only for objects with category field)
        def add_field_error(form, field_name, message):
                err_list = ErrorList( (message,) )
                form._errors[field_name] = err_list
        user = self.form._magic_user

        # Adding new object
        for form in self.extra_forms:
            change_perm = get_permission('change', form.instance)
            if not form.has_changed():
                continue
            if cfield.name not in form.changed_data:
                continue
            add_perm = get_permission('add', form.instance)
            if not has_object_permission(user, form.instance, change_perm):
                self._non_form_errors = _('Creating objects is not permitted.')
                continue
            c = form.cleaned_data[cfield.name]
            if not has_category_permission(user, c, add_perm):
                add_field_error( form, cfield.name, _('Category not permitted') )

        # Changing existing object
        for form in self.initial_forms:
            change_perm = get_permission('change', form.instance)
            delete_perm = get_permission('delete', form.instance)
            if self.can_delete and hasattr(form, 'cleaned_data') and form.cleaned_data[DELETION_FIELD_NAME]:
                if not has_object_permission(user, form.instance, delete_perm):
                    self._non_form_errors = _('Object deletion is not permitted.')
                    continue
                if model_category_fk(form.instance) is not None and not has_category_permission(user, form.instance.category, delete_perm):
                    self._non_form_errors = _('Object deletion is not permitted.')
                    continue
            if cfield.name not in form.changed_data:
                continue
            if not has_object_permission(user, form.instance, change_perm):
                self._non_form_errors = _('Object change is not permitted.')
                continue
            c = form.cleaned_data[cfield.name]
            if not has_category_permission(user, c, change_perm):
                add_field_error( form, cfield.name, _('Category not permitted') )
Example #3
0
    def get_queryset(self):
        user = self.form._magic_user
        if not hasattr(self, '_queryset'):
            if self.queryset is not None:
                qs = self.queryset
            else:
                qs = self.model._default_manager.get_query_set()
            # category based permissions
            if not user.is_superuser:
                category_fk = model_category_fk(self.model)
                if category_fk:
                    # in ListingInlineOptions: self.instance .. Placement instance, self.model .. Listing
                    view_perm = get_permission('view', self.model)
                    change_perm = get_permission('change', self.model)
                    perms = (view_perm, change_perm,)
                    qs = permission_filtered_model_qs(qs, user, perms)
            # user filtered categories
            qs = utils.user_category_filter(qs, user)

            if self.max_num > 0:
                self._queryset = qs[:self.max_num]
            else:
                self._queryset = qs
        return self._queryset
Example #4
0
    def suggest_view(self, request, extra_context=None):
        self.register_newman_variables(request)

        if not ('f' in request.GET.keys() and 'q' in request.GET.keys()):
            raise AttributeError, 'Invalid query attributes. Example: ".../?f=field_a&f=field_b&q=search_term&o=offset"'
        elif len(request.GET.get('q')) < newman_settings.SUGGEST_VIEW_MIN_LENGTH:
            return HttpResponse( '', mimetype='text/plain;charset=utf-8' )

        offset = 0
        if 'o' in request.GET.keys() and request.GET.get('o'):
            offset = int(request.GET.get('o'))
        limit = offset + newman_settings.SUGGEST_VIEW_LIMIT

        model_fields = [mf.name for mf in self.model._meta.fields]
        lookup_fields = []
        lookup_value = request.GET.get('q')
        lookup = None
        has_non_lookup_attr = False
        all_fields = [u'id'] + request.GET.getlist('f')

        for lf in all_fields:
            if lf in model_fields or lf.split('__')[0] in model_fields:
                lookup_fields.append(lf)
            elif hasattr(self.model, lf):
                has_non_lookup_attr = True
            else:
                raise AttributeError, 'Model "%s" has not field "%s". Possible fields are "%s".' \
                                    % (self.model._meta.object_name, lf, ', '.join(model_fields))

        for f in lookup_fields:
            lookup_key = str('%s__icontains' % f)
            if not lookup:
                lookup = models.Q(**{lookup_key: lookup_value})
            else:
                lookup = lookup | models.Q(**{lookup_key: lookup_value})
        # user role based category filtering
        if not is_category_model(self.model):
            category_field = model_category_fk(self.model)
            if category_field and request.user:
                applicable = applicable_categories(request.user)
                args_lookup = { '%s__in' % category_field.name: applicable}
                lookup = lookup & models.Q(**args_lookup)
        else:
            applicable = applicable_categories(request.user)
            lookup = lookup & models.Q(pk__in=applicable)
        # user category filter
        qs = utils.user_category_filter(self.model.objects.filter(lookup), request.user)

        if not has_non_lookup_attr:
            data = qs.values(*lookup_fields)
        else:
            data = qs.only(*lookup_fields)

        def construct_row(inst, fields):
            row = {}
            for f in fields:
                attr = getattr(inst, f)
                if callable(attr):
                    row[f] = attr()
                else:
                    row[f] = attr
                row[f] = truncatewords(striptags(unicode(row[f])), 5)
            return row

        if has_non_lookup_attr:
            outdata = []
            for i in data:
                outdata.append(construct_row(i, all_fields))
            data = outdata

        # sort the suggested items so that those starting with the sought term come first
        def compare(a,b):
            def _cmp(a,b,sought):
                a_starts = unicode(a).lower().startswith(sought)
                b_starts = unicode(b).lower().startswith(sought)
                # if exactly one of (a,b) starts with sought, the one starting with it comes first
                if a_starts ^ b_starts:
                    if a_starts: return -1
                    if b_starts: return +1
                # else compare lexicographically
                return cmp(a,b)
            return _cmp(a,b,unicode(lookup_value).lower())
        cnt = len(data)
        data = list(data)
        if offset >= len(data): return HttpResponse('SPECIAL: OFFSET OUT OF RANGE', mimetype='text/plain')
        data.sort(cmp=compare, key=lambda x: x[lookup_fields[1]])
        data = data[offset:limit]

        ft = []
        ft.append('{cnt:%d}' % cnt)
        for item in data:
            ft.append( "%s".encode('utf-8') % '|'.join("%s" % item[f] for f in all_fields) )

        return HttpResponse( '\n'.join(ft), mimetype='text/plain;charset=utf-8' )
 def test_model_category_fk_from_article(self):
     tools.assert_equals(self.article_fields['category'], model_category_fk(Article))