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