From ee38a04ffb41677cfb2891de3008bbfe7fb14360 Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Mon, 24 Jan 2011 19:14:38 +0530 Subject: [PATCH] access --- pandora/item/managers.py | 1 + pandora/item/models.py | 50 ++++++++++++++++++++++++------- pandora/item/views.py | 63 ++++++++++++++++++++-------------------- 3 files changed, 73 insertions(+), 41 deletions(-) diff --git a/pandora/item/managers.py b/pandora/item/managers.py index f2fde897f..09e8fc297 100644 --- a/pandora/item/managers.py +++ b/pandora/item/managers.py @@ -7,6 +7,7 @@ from django.db.models import Q, Manager from itemlist.models import List import models + def parseCondition(condition): ''' condition: { diff --git a/pandora/item/models.py b/pandora/item/models.py index ce81d5e02..9d6f8401d 100644 --- a/pandora/item/models.py +++ b/pandora/item/models.py @@ -23,7 +23,7 @@ import utils import tasks from archive import extract -from annotaion.models import Annotation +from annotaion.models import Annotation, Layer from person.models import get_name_sort from app.models import site_config @@ -124,6 +124,21 @@ class Item(models.Model): return self.external_data[key] return default + def access(self, user): + if user.is_authenticated(): + access, created = Access.objects.get_or_create(item=self, user=user) + else: + access, created = Access.objects.get_or_create(item=self, user=None) + access.save() + + if self.public and self.available: + return True + elif user.is_staff or \ + self.user == user or \ + self.groups.filter(id__in=user.groups.all()).count() > 0: + return True + return False + def editable(self, user): if user.is_staff or \ self.user == user or \ @@ -319,11 +334,15 @@ class Item(models.Model): layers = {} layers['cuts'] = self.data.get('cuts', {}) - layers['subtitles'] = {} - #FIXME: subtitles should be stored in Annotation + layers['subtitles'] = [] + #FIXME: should subtitles be stored in Annotation? qs = self.files.filter(is_subtitle=True, is_main=True, available=True) if qs.count()>0: layers['subtitles'] = qs[0].srt() + for l in Layer.objects.all(): + ll = layers.setdefault(l.name, []) + for a in Annotation.objects.filter(layer=l, item=self).order_by('start'): + ll.append(a.json()) return layers def get_json(self, fields=None): @@ -351,8 +370,6 @@ class Item(models.Model): if isinstance(i[key], datetime): i[key] = i[key].strftime('%Y-%m-%dT%H:%M:%SZ') - if not fields: - i['stream'] = self.get_stream() i['poster'] = self.get_poster() i['posters'] = self.get_posters() return i @@ -851,11 +868,11 @@ for key in filter(lambda k: 'sort' in k, config['itemKeys']): name = {'id': 'itemId'}.get(name, name) sort_type = key['sort'].get('type', key['type']) model = { - 'char': (models.CharField, dict(max_length=1000, db_index=True)), - 'year': (models.CharField, dict(max_length=4, db_index=True)), - 'integer': (models.BigIntegerField, dict(blank=True, db_index=True)), - 'float': (models.FloatField, dict(blank=True, db_index=True)), - 'date': (models.DateTimeField, dict(blank=True, db_index=True)) + 'char': (models.CharField, dict(null=True, max_length=1000, db_index=True)), + 'year': (models.CharField, dict(null=True, max_length=4, db_index=True)), + 'integer': (models.BigIntegerField, dict(null=True, blank=True, db_index=True)), + 'float': (models.FloatField, dict(null=True, blank=True, db_index=True)), + 'date': (models.DateTimeField, dict(null=True, blank=True, db_index=True)) }[{ 'string': 'char', 'title': 'char', @@ -875,6 +892,19 @@ ItemSort.descending_fields = filter(lambda x: x.endswith('_desc'), [f.name for f in ItemSort._meta.fields]) +class Access(models.Model): + class Meta: + unique_together = ("item", "user") + + access = models.DateTimeField(auto_now=True) + item = models.ForeignKey(Item, related_name='accessed') + user = models.ForeignKey(User, null=True, related_name='accessed_items') + + def __unicode__(self): + if self.user: + return u"%s/%s/%s" % (self.user, self.item, self.access) + return u"%s/%s" % (self.item, self.access) + class Facet(models.Model): ''' used for keys that can have multiple values like people, languages etc. diff --git a/pandora/item/views.py b/pandora/item/views.py index 74485863c..52cccb771 100644 --- a/pandora/item/views.py +++ b/pandora/item/views.py @@ -57,6 +57,23 @@ def _order_query(qs, sort, prefix='sort__'): qs = qs.order_by(*order_by) return qs +def _order_by_group(query): + if 'sort' in query: + if len(query['sort']) == 1 and query['sort'][0]['key'] == 'items': + if query['group'] == "year": + order_by = query['sort'][0]['operator'] == '-' and 'items' or '-items' + else: + order_by = query['sort'][0]['operator'] == '-' and '-items' or 'items' + if query['group'] != "keyword": + order_by = (order_by, 'value_sort') + else: + order_by = (order_by,) + else: + order_by = query['sort'][0]['operator'] == '-' and '-value_sort' or 'value_sort' + order_by = (order_by, 'items') + else: + order_by = ('-value_sort', 'items') + return order_by def _parse_query(data, user): query = {} @@ -149,46 +166,27 @@ Positions response = json_response({}) if 'group' in query: - if 'sort' in query: - if len(query['sort']) == 1 and query['sort'][0]['key'] == 'items': - if query['group'] == "year": - order_by = query['sort'][0]['operator'] == '-' and 'items' or '-items' - else: - order_by = query['sort'][0]['operator'] == '-' and '-items' or 'items' - if query['group'] != "keyword": - order_by = (order_by, 'value_sort') - else: - order_by = (order_by,) - else: - order_by = query['sort'][0]['operator'] == '-' and '-value_sort' or 'value_sort' - order_by = (order_by, 'items') - else: - order_by = ('-value_sort', 'items') response['data']['items'] = [] items = 'items' item_qs = query['qs'] + order_by = _order_by_group(query) qs = models.Facet.objects.filter(key=query['group']).filter(item__id__in=item_qs) qs = qs.values('value').annotate(items=Count('id')).order_by(*order_by) if 'ids' in query: - #FIXME: this does not scale for larger results response['data']['positions'] = {} ids = [j['value'] for j in qs] response['data']['positions'] = utils.get_positions(ids, query['ids']) - elif 'range' in data: qs = qs[query['range'][0]:query['range'][1]] response['data']['items'] = [{'name': i['value'], 'items': i[items]} for i in qs] else: response['data']['items'] = qs.count() elif 'ids' in query: - #FIXME: this does not scale for larger results qs = _order_query(query['qs'], query['sort']) - response['data']['positions'] = {} ids = [j['itemId'] for j in qs.values('itemId')] response['data']['positions'] = utils.get_positions(ids, query['ids']) - elif 'keys' in query: response['data']['items'] = [] qs = _order_query(query['qs'], query['sort']) @@ -201,11 +199,11 @@ Positions r[p] = m.get(p, '') return r qs = qs[query['range'][0]:query['range'][1]] - #response['data']['items'] = [only_p(m.get_json()) for m in qs] + #response['data']['items'] = [m.get_json(_p) for m in qs] response['data']['items'] = [only_p(m['json']) for m in qs.values('json')] else: # otherwise stats items = query['qs'] - files = File.objects.all().filter(item__in=items).exclude(size__gt=0) + files = File.objects.all().filter(item__in=items).filter(size__gt=0) r = files.aggregate( Sum('duration'), Sum('pixels'), @@ -215,12 +213,13 @@ Positions response['data']['files'] = files.count() response['data']['items'] = items.count() response['data']['pixels'] = r['pixels__sum'] - response['data']['runtime'] = items.filter(sort__runtime_desc__gt=0).aggregate(Sum('sort__runtime_desc'))['sort__runtime_desc__sum'] - if response['data']['runtime'] == None: - response['data']['runtime'] = 1337 + response['data']['runtime'] = items.filter(sort__runtime_desc__gt=0).aggregate( + Sum('sort__runtime_desc'))['sort__runtime_desc__sum'] response['data']['size'] = r['size__sum'] + for key in ('runtime', 'duration', 'pixels', 'size'): + if response['data'][key] == None: + response['data'][key] = 0 return render_to_json_response(response) - actions.register(find) @@ -287,11 +286,13 @@ def getItem(request): response = json_response({}) itemId = json.loads(request.POST['data']) item = get_object_or_404_json(models.Item, itemId=itemId) - #FIXME: check permissions - info = item.get_json() - info['stream'] = item.get_stream() - info['layers'] = item.get_layers() - response['data'] = {'item': info} + if item.access(request.user): + info = item.get_json() + info['stream'] = item.get_stream() + info['layers'] = item.get_layers() + response['data']['item'] = info + else: + response = json_response(status=403, text='permission denied') return render_to_json_response(response) actions.register(getItem)