From 0ebc9b5f32586413dfe4605dfe9864b7fff353a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20Pokorn=C3=A1?= Date: Tue, 1 Dec 2020 23:52:03 +0100 Subject: [PATCH] =?UTF-8?q?views=5Fall=20|=20filtrov=C3=A1n=C3=AD=20json-u?= =?UTF-8?q?=20podle=20pr=C3=A1v=20u=C5=BEivatele?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- seminar/models.py | 11 +++-- seminar/views/views_all.py | 90 ++++++++++++++++++++++++++++---------- seminar/viewsets.py | 25 ----------- 3 files changed, 74 insertions(+), 52 deletions(-) diff --git a/seminar/models.py b/seminar/models.py index 57a44404..7b4ce05d 100644 --- a/seminar/models.py +++ b/seminar/models.py @@ -745,15 +745,18 @@ class Problem(SeminarModelBase,PolymorphicModel): def verejne(self): # aktuálně podle stavu problému # FIXME pro některé problémy možná chceme override + # FIXME vrací veřejnost čistě problému, nezávisle na čísle, ve kterém je. + # Je to tak správně? stav_verejny = False if self.stav == 'zadany' or self.stav == 'vyreseny': stav_verejny = True + return stav_verejny - cislo_verejne = False - if (self.cislo_zadani and self.cislo_zadani.verejne()): - cislo_verejne = True + #cislo_verejne = False + #if (self.cislo_zadani and self.cislo_zadani.verejne()): + # cislo_verejne = True - return (stav_verejny and cislo_verejne) + #return (stav_verejny and cislo_verejne) verejne.boolean = True def verejne_url(self): diff --git a/seminar/views/views_all.py b/seminar/views/views_all.py index a550c40a..79b75b0f 100644 --- a/seminar/views/views_all.py +++ b/seminar/views/views_all.py @@ -1,4 +1,4 @@ -# coding:utf-8 + from django.shortcuts import get_object_or_404, render, redirect from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, JsonResponse @@ -17,6 +17,7 @@ from django.contrib.auth.models import User, Permission from django.contrib.auth.mixins import LoginRequiredMixin from django.db import transaction from django.core import serializers +from django.core.exceptions import PermissionDenied from django.forms.models import model_to_dict import seminar.models as s @@ -120,15 +121,57 @@ class TNLData(object): self.appendable_siblings = tnltt.appendableChildren(self.parent) else: self.appendable_siblings = [] - - + @classmethod + def public_above(cls, anode): + """ Returns output of verejne for closest Rocnik, Cislo or Problem above. + (All of them have method verejne.)""" + parent = anode # chceme začít už od konkrétního node včetně + while True: + rocnik = isinstance(parent, s.RocnikNode) + cislo = isinstance(parent, s.CisloNode) + uloha = (isinstance(parent, s.UlohaVzorakNode) or + isinstance(parent, s.UlohaZadaniNode)) + tema = isinstance(parent, s.TemaVCisleNode) + + if (rocnik or cislo or uloha or tema) or parent==None: + break + else: + parent = treelib.get_parent(parent) + if rocnik: + return parent.rocnik.verejne() + elif cislo: + return parent.cislo.verejne() + elif uloha: + return parent.uloha.verejne() + elif tema: + return parent.tema.verejne() + elif None: + print("Existuje TreeNode, který není pod číslem, ročníkem, úlohou" + "ani tématem. {}".format(anode)) + return False + + @classmethod + def all_public_children(cls, anode): + for ch in treelib.all_children(anode): + if TNLData.public_above(ch): + yield ch + else: + continue @classmethod - def from_treenode(cls,anode,parent=None,index=None): - out = cls(anode,parent,index) - for (idx,ch) in enumerate(treelib.all_children(anode)): - # FIXME přidat filtrování na veřejnost - outitem = cls.from_treenode(ch,out,idx) + def from_treenode(cls, anode, user, parent=None, index=None): + if TNLData.public_above(anode) or user.has_perm('auth.org'): + out = cls(anode,parent,index) + else: + raise PermissionDenied() + + if user.has_perm('auth.org'): + enum_children = enumerate(treelib.all_children(anode)) + else: + enum_children = enumerate(TNLData.all_public_children(anode)) + + for (idx,ch) in enum_children: + outitem = cls.from_treenode(ch, user, out, idx) out.children.append(outitem) out.add_edit_options() return out @@ -195,7 +238,7 @@ class TreeNodeView(generic.DetailView): def get_context_data(self,**kwargs): context = super().get_context_data(**kwargs) - context['tnldata'] = TNLData.from_treenode(self.object) + context['tnldata'] = TNLData.from_treenode(self.object,self.request.user) return context class TreeNodeJSONView(generic.DetailView): @@ -203,7 +246,7 @@ class TreeNodeJSONView(generic.DetailView): def get(self,request,*args, **kwargs): self.object = self.get_object() - data = TNLData.from_treenode(self.object).to_json() + data = TNLData.from_treenode(self.object,self.request.user).to_json() return JsonResponse(data) @@ -332,6 +375,7 @@ class ProblemView(generic.DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + user = self.request.user # Teď potřebujeme doplnit tnldata do kontextu. # Ošklivý type switch, hezčí by bylo udělat to polymorfni. FIXME. if False: @@ -339,11 +383,11 @@ class ProblemView(generic.DetailView): pass elif isinstance(self.object, s.Clanek) or isinstance(self.object, s.Konfera): # Tyhle Problémy mají ŘešeníNode - context['tnldata'] = TNLData.from_treenode(self.object.reseninode) + context['tnldata'] = TNLData.from_treenode(self.object.reseninode,user) elif isinstance(self.object, s.Uloha): # FIXME: Teď vždycky zobrazujeme i vzorák! Možná by bylo hezčí/lepší mít to stejně jako pro Téma: procházet jen dosažitelné z Ročníku / čísla / whatever - tnl_zadani = TNLData.from_treenode(self.object.ulohazadaninode) - tnl_vzorak = TNLData.from_treenode(self.object.ulohavzoraknode) + tnl_zadani = TNLData.from_treenode(self.object.ulohazadaninode,user) + tnl_vzorak = TNLData.from_treenode(self.object.ulohavzoraknode,user) context['tnldata'] = TNLData.from_tnldata_list([tnl_zadani, tnl_vzorak]) elif isinstance(self.object, s.Tema): rocniknode = self.object.rocnik.rocniknode @@ -385,16 +429,16 @@ class AktualniZadaniView(generic.TemplateView): # ) # def ZadaniTemataView(request): - nastaveni = get_object_or_404(Nastaveni) - verejne = nastaveni.aktualni_cislo.verejne() - akt_rocnik = nastaveni.aktualni_cislo.rocnik - temata = s.Tema.objects.filter(rocnik=akt_rocnik, stav='zadany') - return render(request, 'seminar/tematka/rozcestnik.html', - { - 'tematka': temata, - 'verejne': verejne, - }, - ) + nastaveni = get_object_or_404(Nastaveni) + verejne = nastaveni.aktualni_cislo.verejne() + akt_rocnik = nastaveni.aktualni_cislo.rocnik + temata = s.Tema.objects.filter(rocnik=akt_rocnik, stav='zadany') + return render(request, 'seminar/tematka/rozcestnik.html', + { + 'tematka': temata, + 'verejne': verejne, + }, + ) # nastaveni = get_object_or_404(Nastaveni) diff --git a/seminar/viewsets.py b/seminar/viewsets.py index cc59f7d7..087d07d6 100644 --- a/seminar/viewsets.py +++ b/seminar/viewsets.py @@ -18,31 +18,6 @@ class PermissionMixin(object): # návštěvník nemusí být zalogován, aby si prohlížel obsah return [permission() for permission in permission_classes] - def verejne_nad(self, node): - """ Returns output of verejne for closest Rocnik, Cislo or Problem above. - (All of them have method verejne.)""" - parent = get_parent(node) - while True: - rocnik = isinstance(parent, RocnikNode) - cislo = isinstance(parent, CisloNode) - problem = isinstance(parent, ProblemNode) - - if (rocnik or cislo or problem): - break - else: - parent = get_parent(parent) - if rocnik: - return parent.rocnik.verejne() - elif cislo: - return parent.cislo.verejne() - elif problem: - return parent.problem.verjne() - - def has_object_permission(self, request, view, obj): - # test that obj is Node - assert isinstance(obj, Node) - return verejne_nad(node) - class ReadWriteSerializerMixin(object): """ Overrides get_serializer_class to choose the read serializer