def test_password_access(self): self.assertEqual(0, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.create(user=self.user, content_object=self.presentation_password, read=True) self.assertEqual(0, get_media_for_record(self.record, user=self.user).count()) passwords = dict(((self.presentation_password.id, 'test'),)) self.assertEqual(1, get_media_for_record(self.record, user=self.user, passwords=passwords).count()) AccessControl.objects.filter(user=self.user).delete()
def test_simple_presentation_access(self): self.assertEqual(0, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.create(user=self.user, content_object=self.presentation_broken, read=True) self.assertEqual(0, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.create(user=self.user, content_object=self.presentation_ok, read=True) self.assertEqual(1, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.filter(user=self.user).delete()
def test_direct_access(self): self.assertEqual(0, get_media_for_record( self.record, user=self.user).count()) AccessControl.objects.create( user=self.user, content_object=self.collection, read=True) self.assertEqual(1, get_media_for_record( self.record, user=self.user).count()) AccessControl.objects.filter(user=self.user).delete()
def test_standalone_record_access(self): self.assertEqual(0, get_media_for_record( self.record_standalone, user=self.user).count()) AccessControl.objects.create( user=self.user, content_object=self.presentation_standalone_record, read=True ) self.assertEqual(1, get_media_for_record( self.record_standalone, user=self.user).count())
def test_hidden_presentation_access(self): self.assertEqual(0, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.create(user=self.user, content_object=self.presentation_hidden, read=True) self.assertEqual(0, get_media_for_record(self.record, user=self.user).count()) self.presentation_hidden.hidden = False self.presentation_hidden.save() self.assertEqual(1, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.filter(user=self.user).delete() self.presentation_hidden.hidden = True self.presentation_hidden.save()
def test_direct_access(self): self.assertEqual( 0, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.create(user=self.user, content_object=self.collection, read=True) self.assertEqual( 1, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.filter(user=self.user).delete()
def test_presentation_must_contain_record(self): self.assertEqual(0, get_media_for_record( self.record, user=self.user).count()) AccessControl.objects.create( user=self.user, content_object=self.presentation_no_record, read=True ) self.assertEqual(0, get_media_for_record( self.record, user=self.user).count()) AccessControl.objects.filter(user=self.user).delete()
def test_presentation_must_contain_record(self): self.assertEqual( 0, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.create( user=self.user, content_object=self.presentation_no_record, read=True) self.assertEqual( 0, get_media_for_record(self.record, user=self.user).count()) AccessControl.objects.filter(user=self.user).delete()
def test_standalone_record_access(self): self.assertEqual( 0, get_media_for_record(self.record_standalone, user=self.user).count()) AccessControl.objects.create( user=self.user, content_object=self.presentation_standalone_record, read=True) self.assertEqual( 1, get_media_for_record(self.record_standalone, user=self.user).count())
def retrieve_pseudostream(request, recordid, record, mediaid, media): mediaobj = get_media_for_record(recordid, request.user).get(id=mediaid) q = dict() start = request.GET.get('start', '') if start.isdigit(): q['start'] = start end = request.GET.get('end', '') if end.isdigit(): q['end'] = end client = request.GET.get('client') if client: q['client'] = client url = mediaobj.storage.urlbase url = url + ('/' if not url.endswith('/') else '') + \ mediaobj.url.replace('\\', '/') if q: url = url + '?' + urlencode(q) try: result = urlopen(url) response = HttpResponse( FileWrapper(result), content_type=result.info().get('Content-Type') ) response['Content-Length'] = result.info().get('Content-Length') return response except HTTPError, e: return HttpResponse(status=e.errno)
def retrieve_pseudostream(request, recordid, record, mediaid, media): mediaobj = get_media_for_record(recordid, request.user).get(id=mediaid) q = dict() start = request.GET.get('start', '') if start.isdigit(): q['start'] = start end = request.GET.get('end', '') if end.isdigit(): q['end'] = end client = request.GET.get('client') if client: q['client'] = client url = mediaobj.storage.urlbase url = url + ('/' if not url.endswith('/') else '') + \ mediaobj.url.replace('\\', '/') if q: url = url + '?' + urlencode(q) try: result = urlopen(url) response = HttpResponse(FileWrapper(result), content_type=result.info().get('Content-Type')) response['Content-Length'] = result.info().get('Content-Length') return response except HTTPError, e: return HttpResponse(status=e.errno)
def retrieve(request, recordid, record, mediaid, media): # check if media exists mediaobj = get_media_for_record(recordid, request.user).filter(id=mediaid) # check download status if not mediaobj or not mediaobj[0].is_downloadable_by(request.user): return HttpResponseForbidden() mediaobj = mediaobj[0] # Allow passing in an argument to prevent setting "attachment" content # disposition, which keeps e.g. the PDF viewer built into Google Chrome # from working inline = request.GET.has_key('inline') name = smart_str(mediaobj.url) if mediaobj.is_local(): # support byte range requests try: content_file = mediaobj.get_absolute_file_path() except IOError: logging.error( "mediaobj.get_absolute_file_path() failed for media.id %s" % mediaid) raise Http404() retval = RangedFileResponse(request, open(content_file, 'r'), content_type=str(mediaobj.mimetype)) else: try: content = mediaobj.load_file() except IOError: logging.error("mediaobj.load_file() failed for media.id %s" % mediaid) raise Http404() if content: retval = HttpResponse(content=content, content_type=str(mediaobj.mimetype)) else: inline = True retval = HttpResponseRedirect(mediaobj.get_absolute_url()) if not inline: retval["Content-Disposition"] = \ 'attachment; filename="%s"' % name Activity.objects.create(event='media-download', request=request, content_object=mediaobj) return retval
def retrieve(request, recordid, record, mediaid, media): # check if media exists mediaobj = get_media_for_record(recordid, request.user).filter(id=mediaid) # check download status if not mediaobj or not mediaobj[0].is_downloadable_by(request.user): return HttpResponseForbidden() mediaobj = mediaobj[0] try: content = mediaobj.load_file() except IOError: raise Http404() Activity.objects.create(event='media-download', request=request, content_object=mediaobj) if content: return HttpResponse(content=content, mimetype=str(mediaobj.mimetype)) else: return HttpResponseRedirect(mediaobj.get_absolute_url())
def retrieve(request, recordid, record, mediaid, media): print 'retrieve' # check if media exists mediaobj = get_media_for_record(recordid, request.user).filter(id=mediaid) # check download status if not mediaobj or not mediaobj[0].is_downloadable_by(request.user): return HttpResponseForbidden() mediaobj = mediaobj[0] try: content = mediaobj.load_file() except IOError: raise Http404() Activity.objects.create(event='media-download', request=request, content_object=mediaobj) if content: return HttpResponse(content=content, mimetype=str(mediaobj.mimetype)) else: return HttpResponseRedirect(mediaobj.get_absolute_url())
def slide_manifest(request, slide, owner, offline=False): fieldvalues = slide.get_fieldvalues(owner=owner) title = slide.title_from_fieldvalues(fieldvalues) or 'Untitled', id = get_id(request, 'slide', 'canvas', 'slide%d' % slide.id) image = slide.record.get_image_url( force_reprocess=False, handler='storage-retrieve-iiif-image', ) metadata = get_metadata(fieldvalues) if slide.annotation: metadata.insert(0, dict(label='Annotation', value=slide.annotation)) passwords = request.session.get('passwords', dict()) media = get_media_for_record(slide.record, request.user, passwords) if len(media): media = media[0] media.identify(lazy=True) canvas_width = width = media.width or 1600 canvas_height = height = media.height or 1200 else: width = height = None canvas_width = 1200 canvas_height = 1200 while canvas_height < 1200 or canvas_width < 1200: canvas_height *= 2 canvas_width *= 2 if width and height: resource = { '@id': image, '@type': 'dctypes:Image', 'format': 'image/jpeg', "height": height, "width": width } if not offline: resource['service'] = { '@context': 'http://iiif.io/api/image/2/context.json', '@id': image, 'profile': 'http://iiif.io/api/image/2/level1.json' } images = [{ '@type': 'oa:Annotation', 'motivation': 'sc:painting', 'resource': resource, 'on': id, }] else: return special_slide( request, kind='missing', label='Missing image', index=slide.id, offline=offline, ) result = { '@id': id, '@type': 'sc:Canvas', 'label': title, "height": canvas_height, "width": canvas_width, 'images': images, 'metadata': metadata, } if offline: result['thumbnail'] = { '@id': '/thumbs' + image, } return result
def record( request, id, name, contexttype=None, contextid=None, contextname=None, edit=False, customize=False, personal=False, copy=False, copyid=None, copyname=None, ): writable_collections = list(accessible_ids(request.user, Collection, write=True)) readable_collections = list(accessible_ids(request.user, Collection)) can_edit = request.user.is_authenticated() can_manage = False if id and name: record = Record.get_or_404(id, request.user) # if the user passes the first test if record: # if the user can't see an image, and there is one, then # don't let them see the record passwords = request.session.get("passwords", dict()) media = get_media_for_record(record, request.user, passwords) unfiltered_media = Media.objects.filter(record__id=record.id) if not media and unfiltered_media: raise Http404() can_edit = can_edit and record.editable_by(request.user) can_manage = record.manageable_by(request.user) else: if request.user.is_authenticated() and (writable_collections or (personal and readable_collections)): record = Record() if personal: record.owner = request.user else: raise Http404() if record.owner: valid_collections = set(readable_collections) | set(writable_collections) else: valid_collections = writable_collections context = None if contexttype and contextid: app_label, model = contexttype.split(".") model_class = get_object_or_404(ContentType, app_label=app_label, model=model).model_class() context = get_object_or_404(filter_by_access(request.user, model_class), id=contextid) media = Media.objects.select_related().filter(record=record, storage__id__in=accessible_ids(request.user, Storage)) # Only list media that is downloadable or editable for m in media: # Calculate permissions and store with object for later use in template m.downloadable_in_template = m.is_downloadable_by(request.user) m.editable_in_template = m.editable_by(request.user) media = filter(lambda m: m.downloadable_in_template or m.editable_in_template, media) edit = edit and request.user.is_authenticated() copyrecord = Record.get_or_404(copyid, request.user) if copyid else None class FieldSetForm(forms.Form): fieldset = FieldSetChoiceField(user=request.user, default_label="Default" if not edit else None) fieldsetform = FieldSetForm(request.GET) if fieldsetform.is_valid(): fieldset = ( FieldSet.for_user(request.user).get(id=fieldsetform.cleaned_data["fieldset"]) if fieldsetform.cleaned_data["fieldset"] else None ) elif (edit or customize) and (id and name): # if we're editing, touch all the data (no default fieldset) fieldset = None else: # use default fieldset settings if settings.DEFAULT_FIELDSET and isinstance(settings.DEFAULT_FIELDSET, basestring): default_fieldset = settings.DEFAULT_FIELDSET else: # yes, it's a default default setting default_fieldset = "dc" fieldset = FieldSet.objects.get(name=default_fieldset) collection_items = collectionformset = None if edit: if not can_edit and not customize and not context: return HttpResponseRedirect(reverse("data-record", kwargs=dict(id=id, name=name))) def _field_choices(): fsf = list( FieldSetField.objects.select_related("fieldset", "field") .all() .order_by("fieldset__name", "order", "field__label") ) grouped = {} for f in fsf: grouped.setdefault((f.fieldset.title, f.fieldset.id), []).append(f.field) others = list( Field.objects.exclude(id__in=[f.field.id for f in fsf]).order_by("label").values_list("id", "label") ) choices = [("", "-" * 10)] + [ (set[0], [(f.id, f.label) for f in fields]) for set, fields in sorted(grouped.iteritems(), key=lambda s: s[0][0]) ] if others: choices.append(("Others", others)) return choices class FieldValueForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(FieldValueForm, self).__init__(*args, **kwargs) def clean_field(self): return Field.objects.get(id=self.cleaned_data["field"]) def clean_context_type(self): context = self.cleaned_data.get("context_type") if context: context = ContentType.objects.get(id=context) return context def clean(self): cleaned_data = self.cleaned_data return cleaned_data field = forms.ChoiceField(choices=_field_choices()) value = forms.CharField(widget=forms.Textarea, required=False) context_type = forms.IntegerField(widget=forms.HiddenInput, required=False) context_id = forms.IntegerField(widget=forms.HiddenInput, required=False) index_value = forms.CharField(widget=forms.HiddenInput, required=False) class Meta: model = FieldValue exclude = [] class CollectionForm(forms.Form): id = forms.IntegerField(widget=forms.HiddenInput) title = forms.CharField(widget=DisplayOnlyTextWidget) member = forms.BooleanField(required=False) shared = forms.BooleanField(required=False) fieldvalues_readonly = [] if customize or context: fieldvalues = record.get_fieldvalues(owner=request.user, context=context, hidden=True).filter( owner=request.user ) else: fieldvalues = record.get_fieldvalues(hidden=True) FieldValueFormSet = modelformset_factory( FieldValue, form=FieldValueForm, exclude=FieldValueForm.Meta.exclude, can_delete=True, extra=3 ) CollectionFormSet = formset_factory(CollectionForm, extra=0) if request.method == "POST": formset = FieldValueFormSet(request.POST, request.FILES, queryset=fieldvalues, prefix="fv") collectionformset = ( CollectionFormSet(request.POST, request.FILES, prefix="c") if not (customize or context) else None ) if formset.is_valid() and ( customize or context or collectionformset.is_valid() ): # or metadataform.is_valid()): record.save() if not (customize or context): collections = dict( (c["id"], c) for c in collectionformset.cleaned_data if c["id"] in valid_collections ) for item in record.collectionitem_set.filter(collection__in=valid_collections): if collections.has_key(item.collection_id): if not collections[item.collection_id]["member"]: item.delete() elif collections[item.collection_id]["shared"] == item.hidden: item.hidden = not item.hidden item.save() del collections[item.collection_id] for coll in collections.values(): if coll["member"]: CollectionItem.objects.create( record=record, collection_id=coll["id"], hidden=not coll["shared"] ) instances = formset.save(commit=False) o1 = fieldvalues and max(v.order for v in fieldvalues) or 0 o2 = instances and max(v.order for v in instances) or 0 order = max(o1, o2, 0) for instance in instances: if not instance.value: if instance.id: instance.delete() continue instance.record = record if instance.order == 0: order += 1 instance.order = order if customize or context: instance.owner = request.user if context: instance.context = context instance.save() request.user.message_set.create(message="Record saved successfully.") url = reverse( "data-record-edit-customize" if customize else "data-record-edit", kwargs=dict(id=record.id, name=record.name), ) next = request.GET.get("next", reverse("data-record", kwargs=dict(id=record.id, name=record.name))) return HttpResponseRedirect(url if request.POST.has_key("save_and_continue") else next) else: if copyrecord: initial = [] for fv in copyrecord.get_fieldvalues(hidden=True): initial.append( dict( label=fv.label, field=fv.field_id, refinement=fv.refinement, value=fv.value, date_start=fv.date_start, date_end=fv.date_end, numeric_value=fv.numeric_value, language=fv.language, order=fv.order, group=fv.group, hidden=fv.hidden, ) ) FieldValueFormSet.extra = len(initial) + 3 elif fieldset: needed = ( fieldset.fields.filter(~Q(id__in=[fv.field_id for fv in fieldvalues])) .order_by("fieldsetfield__order") .values_list("id", flat=True) ) initial = [{}] * len(fieldvalues) + [{"field": id} for id in needed] FieldValueFormSet.extra = len(needed) + 3 else: initial = [] formset = FieldValueFormSet(queryset=fieldvalues, prefix="fv", initial=initial) if not (customize or context): collections = dict( ( (coll.id, dict(id=coll.id, title=coll.title)) for coll in Collection.objects.filter(id__in=valid_collections) ) ) for item in (copyrecord or record).collectionitem_set.all(): collections.get(item.collection_id, {}).update(dict(member=True, shared=not item.hidden)) collections = sorted(collections.values(), key=lambda c: c["title"]) collectionformset = CollectionFormSet(prefix="c", initial=collections) else: fieldvalues_readonly = record.get_fieldvalues(owner=request.user, fieldset=fieldset) formset = None q = Q() if record.owner == request.user or request.user.is_superuser else Q(hidden=False) collection_items = record.collectionitem_set.filter(q, collection__in=readable_collections) if can_edit: from rooibos.storage.views import media_upload_form UploadFileForm = media_upload_form(request) upload_form = UploadFileForm() if UploadFileForm else None else: upload_form = None # handle uploading over secure URLs: in the view, offer link to insecure insecure_url = None if request.is_secure() and settings.INSECURE_UPLOAD: request_url = request.build_absolute_uri(request.get_full_path()) insecure_url = request_url.replace("https://", "http://") record_usage = record.presentationitem_set.values("presentation").distinct().count() if can_edit else 0 return render_to_response( "data_record.html", { "record": record, "media": media, "fieldsetform": fieldsetform, "fieldset": fieldset, "fieldvalues": fieldvalues_readonly, "context": context, "customize": customize, "fv_formset": formset, "c_formset": collectionformset, "can_edit": can_edit, "can_manage": can_manage, "next": request.GET.get("next"), "collection_items": collection_items, "upload_form": upload_form, "upload_url": ( "%s?sidebar&next=%s" % (reverse("storage-media-upload", args=(record.id, record.name)), request.get_full_path()) ) if record.id else None, "insecure_url": insecure_url, "record_usage": record_usage, }, context_instance=RequestContext(request), )