Example #1
0
def retrieve_pseudostream(request, recordid, record, mediaid, media):

    mediaobj = get_object_or_404(Media.objects.filter(id=mediaid,
                                 record__id=recordid,
                                 record__collection__id__in=accessible_ids(request.user, Collection),
                                 storage__id__in=accessible_ids(request.user, Storage)).distinct())

    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)
Example #2
0
    def filter_by_access(user, *ids):
        records = Record.objects.distinct()

        ids = map(int, ids)

        if user:

            if user.is_superuser:
                return records.filter(id__in=ids)

            accessible_records = cache_get_many(
                ['record-access-%d-%d' % (user.id or 0, id) for id in ids],
                model_dependencies=[Record, Collection, AccessControl]
            )
            accessible_record_ids = map(lambda (k, v): (int(k.rsplit('-', 1)[1]), v), accessible_records.iteritems())

            allowed_ids = [k for k, v in accessible_record_ids if v == 't']
            denied_ids  = [k for k, v in accessible_record_ids if v == 'f']

            to_check = [id for id in ids if not id in allowed_ids and not id in denied_ids]

            if not to_check:
                return records.filter(id__in=allowed_ids)

        else:
            allowed_ids = []
            to_check = ids

        # check which records have individual ACLs set
        individual = _records_with_individual_acl_by_ids(to_check)
        if individual:
            allowed_ids.extend(accessible_ids(user, Record.objects.filter(id__in=individual)))
            to_check = [id for id in to_check if not id in individual]
        # check records without individual ACLs
        if to_check:
            cq = Q(collectionitem__collection__in=accessible_ids(user, Collection),
                   collectionitem__hidden=False)
            mq = Q(collectionitem__collection__in=accessible_ids(user, Collection, write=True),
                   owner=None)
            oq = Q(owner=user) if user and not user.is_anonymous() else Q()
            records = records.filter(cq | mq | oq)
            checked = records.filter(id__in=to_check).values_list('id', flat=True)
            allowed_ids.extend(checked)

        if user:
            cache_update = dict(
                        ('record-access-%d-%d' % (user.id or 0, id), 't' if id in checked else 'f')
                         for id in to_check
                    )
            cache_set_many(cache_update, model_dependencies=[Record, Collection, AccessControl])

        return records.filter(id__in=allowed_ids)
Example #3
0
def powerpoint(request):

    available_storage = get_list_or_404(filter_by_access(request.user, Storage, write=True).order_by('title').values_list('id', 'title'))
    available_collections = get_list_or_404(filter_by_access(request.user, Collection, write=True).order_by('title').values_list('id', 'title'))

    class UploadFileForm(forms.Form):
        title = forms.CharField(max_length=50)
        storage = forms.ChoiceField(choices=available_storage)
        collection = forms.ChoiceField(choices=available_collections)
        file = forms.FileField()

        def clean_file(self):
            file = self.cleaned_data['file']
            if not file.content_type in ('application/vnd.ms-powerpoint',
                                         'application/vnd.openxmlformats-officedocument.presentationml.presentation'):
                raise forms.ValidationError("The selected file does not appear to be a PowerPoint file")
            return file


    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            tempdir = tempfile.mkdtemp()
            infile = form.cleaned_data['file']
            filename = os.path.join(tempdir, 'a.ppt' if infile.content_type == 'application/vnd.ms-powerpoint' else 'a.pptx')
            outfile = open(filename, "wb+")
            for chunk in infile.chunks():
                outfile.write(chunk)
            outfile.close()
            presentation = convert_ppt(request.user,
                                       form.cleaned_data['title'],
                                       Collection.objects.get(id=form.cleaned_data['collection'],
                                                              id__in=accessible_ids(request.user, Collection, write=True)),
                                       Storage.objects.get(id=form.cleaned_data['storage'],
                                                           id__in=accessible_ids(request.user, Storage, write=True)),
                                       tempdir,
                                       filename)
            shutil.rmtree(tempdir)
            if not presentation:
                request.user.message_set.create(message="An error occurred while importing the presentation.")
            else:
                request.user.message_set.create(message="Presentation created successfully.")
                return HttpResponseRedirect(reverse('presentation-edit',
                                                    kwargs=dict(id=presentation.id, name=presentation.name)))
    else:
        form = UploadFileForm()
    return render_to_response('powerpoint.html',
                              {'form': form},
                              context_instance=RequestContext(request))
Example #4
0
def password(request, id, name):

    presentation = get_object_or_404(Presentation.objects.filter(Presentation.published_Q(request.user),
                                id=id,
                                id__in=accessible_ids(request.user, Presentation)))

    class PasswordForm(forms.Form):
        password = forms.CharField(widget=forms.PasswordInput)

        def clean_password(self):
            p = self.cleaned_data.get('password')
            if p != presentation.password:
                raise forms.ValidationError("Password is not correct.")
            return p

    if request.method == 'POST':
        form = PasswordForm(request.POST)
        if form.is_valid():
            request.session.setdefault('passwords', dict())[presentation.id] = form.cleaned_data.get('password')
            return HttpResponseRedirect(request.GET.get('next', reverse('presentation-browse')))
    else:
        form = PasswordForm()

    return render_to_response('presentation_password.html',
                          {'form': form,
                           'presentation': presentation,
                           'next': request.GET.get('next', reverse('presentation-browse')),
                           },
                          context_instance=RequestContext(request))
Example #5
0
def _generate_query(search_facets, user, collection, criteria, keywords, selected, *exclude):

    # add owned tag facet
    search_facets['ownedtag'] = OwnedTagSearchFacet()

    fields = {}
    for c in criteria:
        if (c in exclude) or (':' not in c):
            continue
        (f, o) = c.split(':', 1)
        if f.startswith('-'):
            f = 'NOT ' + f[1:]
        fname = f.rsplit(' ',1)[-1]

        # create exact match criteria on the fly if needed
        if fname.endswith('_s') and not search_facets.has_key(fname):
            search_facets[fname] = ExactValueSearchFacet(fname)

        if search_facets.has_key(fname):
            o = search_facets[fname].process_criteria(o, user)
            fields.setdefault(f, []).append('(' + o.replace('|', ' OR ') + ')')

    fields = map(lambda (name, crit): '%s:(%s)' % (name, (name.startswith('NOT ') and ' OR ' or ' AND ').join(crit)),
                 fields.iteritems())

    def build_keywords(q, k):
        k = k.lower()
        if k == 'and' or k == 'or':
            return q + ' ' + k.upper()
        elif q.endswith(' AND') or q.endswith(' OR'):
            return q + ' ' + k
        else:
            return q + ' AND ' + k

    if keywords: keywords = reduce(build_keywords, keywords.split())

    query = ''
    if fields:
        query = ' AND '.join(fields)
    if keywords:
        query = query and '%s AND (%s)' % (query, keywords) or '(%s)' % keywords
    if not query:
        query = '*:*'
    if collection:
        query = 'collections:%s AND %s' % (collection.id, query)
    if hasattr(selected, '__len__'):
        query = 'id:(%s) AND %s' % (' '.join(map(str, selected or [-1])), query)

    if not user.is_superuser:
        collections = ' '.join(map(str, accessible_ids(user, Collection)))
        c = []
        if collections: c.append('collections:(%s)' % collections)
        if user.id: c.append('owner:%s' % user.id)
        if c:
            query = '(%s) AND %s' % (' OR '.join(c), query)
        else:
            query = 'id:"-1"'

    return query
Example #6
0
def run_search(user,
               collection=None,
               criteria=[],
               keywords='',
               sort='score desc',
               page=1,
               pagesize=25,
               orquery=None,
               selected=False,
               remove=None,
               produce_facets=False):

    available_storage = accessible_ids(user, Storage)
    exclude_facets = ['identifier']
    fields = Field.objects.filter(standard__prefix='dc').exclude(name__in=exclude_facets)

    search_facets = [SearchFacet('tag', 'Tags')] + [SearchFacet(field.name + '_t', field.label) for field in fields]
    search_facets.append(StorageSearchFacet('resolution', 'Image size', available_storage))
    search_facets.append(StorageSearchFacet('mimetype', 'Media type', available_storage))
    search_facets.append(CollectionSearchFacet('allcollections', 'Collection'))
    search_facets.append(OwnerSearchFacet('owner', 'Owner'))
    # convert to dictionary
    search_facets = dict((f.name, f) for f in search_facets)

    query = _generate_query(search_facets, user, collection, criteria, keywords, selected, remove)

    s = SolrIndex()

    return_facets = search_facets.keys() if produce_facets else []

    try:
        (hits, records, facets) = s.search(query, sort=sort, rows=pagesize, start=(page - 1) * pagesize,
                                           facets=return_facets, facet_mincount=1, facet_limit=100)
    except SolrError:
        hits = -1
        records = None
        facets = dict()
    except socket.error:
        hits = 0
        records = None
        facets = dict()

    if produce_facets:
        for f in search_facets:
            search_facets[f].set_result(facets.get(f))

    if orquery:
        (f, v) = orquery.split(':', 1)
        orfacets = s.search(_generate_query(search_facets, user, collection, criteria, keywords, selected,
                                            remove, orquery),
                            rows=0, facets=[f], facet_mincount=1, facet_limit=100)[2]
        orfacet = copy.copy(search_facets[f])
        orfacet.label = '%s in %s or...' % (v.replace("|", " or "), orfacet.label)
        orfacet.set_result(orfacets[f])
    else:
        orfacet = None

    return (hits, records, search_facets, orfacet, query, fields)
Example #7
0
 def _check_permission_for_user(self, user, **permissions):
     # checks if user is owner or has ACL access
     if check_access(user, self, **permissions):
         return True
     # if record does not have individual ACL...
     if len(_records_with_individual_acl_by_ids([self.id])) > 0:
         return False
     # ...check collection access
     return len(accessible_ids(user, self.collection_set, **permissions)) > 0
Example #8
0
 def published_Q(owner=None):
     publish_permission = Permission.objects.get(codename='publish_presentations')
     valid_publishers = User.objects.filter(Q(id__in=publish_permission.user_set.all()) |
                                            Q(groups__id__in=publish_permission.group_set.all()) |
                                            Q(is_superuser=True))
     q = Q(owner__in=valid_publishers) & Q(hidden=False)
     if owner and not owner.is_anonymous():
         return q | Q(id__in=accessible_ids(owner, Presentation, manage=True))
     else:
         return q
Example #9
0
def get_media_for_record(record, user=None, passwords={}):
    """
    Returns all media accessible to the user either directly through collections
    or indirectly through presentations.
    A user always must have access to the storage where the media is stored.
    """
    from rooibos.presentation.models import Presentation

    record_id = getattr(record, 'id', record)
    record = Record.filter_one_by_access(user, record_id)

    if not record:
        # Try to get to record through an accessible presentation -
        # own presentations don't count, since it's already established that owner
        # doesn't have access to the record.
        pw_q = Q(
            # Presentation must not have password
            Q(password=None) | Q(password='') |
            # or must know password
            Q(id__in=Presentation.check_passwords(passwords))
        )
        access_q = Q(
            # Must have access to presentation
            id__in=accessible_ids(user, Presentation),
            # and presentation must not be archived
            hidden=False
        )
        accessible_presentations = Presentation.objects.filter(
            pw_q, access_q, items__record__id=record_id)
        # Now get all the presentation owners so we can check if any of them have access
        # to the record
        owners = User.objects.filter(id__in=accessible_presentations.values('owner'))
        if not any(Record.filter_one_by_access(owner, record_id) for owner in owners):
            return Media.objects.none()

    return Media.objects.filter(
        record__id=record_id,
        storage__id__in=accessible_ids(user, Storage),
        )
Example #10
0
def data_import_file(request, file):

    available_collections = filter_by_access(request.user, Collection)
    writable_collection_ids = accessible_ids(request.user, Collection, write=True)
    if not available_collections:
        raise Http404
    available_fieldsets = FieldSet.for_user(request.user)

    def _get_fields():
        return Field.objects.select_related("standard").all().order_by("standard", "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

    # def _field_choices():
    #    grouped = {}
    #    for f in _get_fields():
    #        grouped.setdefault(f.standard and f.standard.title or 'Other', []).append(f)
    #    return [('0', '[do not import]'), ('-1', '[new field]')] + \
    #           [(g, [(f.id, f.label) for f in grouped[g]]) for g in grouped]

    class ImportOptionsForm(forms.Form):
        separator = forms.CharField(required=False)
        collections = forms.MultipleChoiceField(
            choices=(
                (c.id, "%s%s" % ("*" if c.id in writable_collection_ids else "", c.title))
                for c in sorted(available_collections, key=lambda c: c.title)
            ),
            widget=forms.CheckboxSelectMultiple,
        )
        fieldset = FieldSetChoiceField(user=request.user, default_label="any")
        # forms.ChoiceField(choices=[(0, 'any')] + [(f.id, f.title) for f in available_fieldsets], required=False)
        update = forms.BooleanField(label="Update existing records", initial=True, required=False)
        add = forms.BooleanField(label="Add new records", initial=True, required=False)
        test = forms.BooleanField(label="Test import only", initial=False, required=False)
        personal = forms.BooleanField(label="Personal records", initial=True, required=False)

        def clean(self):
            cleaned_data = self.cleaned_data
            if any(self.errors):
                return cleaned_data
            personal = cleaned_data["personal"]
            if not personal:
                for c in map(int, cleaned_data["collections"]):
                    if not c in writable_collection_ids:
                        self._errors["collections"] = ErrorList(
                            ["Can only add personal records to selected collections"]
                        )
                        del cleaned_data["collections"]
                        return cleaned_data
            return cleaned_data

    class MappingForm(forms.Form):
        fieldname = forms.CharField(widget=DisplayOnlyTextWidget, required=False)
        mapping = forms.ChoiceField(choices=_field_choices(), required=False)
        separate = forms.BooleanField(required=False)
        label = forms.CharField(required=False)
        hidden = forms.BooleanField(required=False)

    class BaseMappingFormSet(forms.formsets.BaseFormSet):
        def clean(self):
            if any(self.errors):
                return
            _dcidentifier = Field.objects.get(name="identifier", standard__prefix="dc")
            _identifier_ids = list(_dcidentifier.get_equivalent_fields().values_list("id", flat=True)) + [
                _dcidentifier.id
            ]
            for i in range(self.total_form_count()):
                if self.forms[i].cleaned_data["mapping"] and (
                    int(self.forms[i].cleaned_data["mapping"]) in _identifier_ids
                ):
                    return
            raise forms.ValidationError, "At least one field must be mapped to an identifier field."

    MappingFormSet = formset_factory(MappingForm, extra=0, formset=BaseMappingFormSet, can_order=True)

    def analyze(collections=None, separator=None, separate_fields=None, fieldset=None):
        try:
            with open(os.path.join(_get_scratch_dir(), _get_filename(request, file)), "rU") as csvfile:
                imp = SpreadsheetImport(
                    csvfile,
                    collections,
                    separator=separator,
                    separate_fields=separate_fields,
                    preferred_fieldset=fieldset,
                )
                return imp, imp.analyze()
        except IOError:
            raise Http404()

    if request.method == "POST":
        form = ImportOptionsForm(request.POST)
        mapping_formset = MappingFormSet(request.POST, prefix="m")
        if form.is_valid() and mapping_formset.is_valid():

            imp, preview_rows = analyze(
                available_collections.filter(id__in=form.cleaned_data["collections"]),
                form.cleaned_data["separator"],
                dict((f.cleaned_data["fieldname"], f.cleaned_data["separate"]) for f in mapping_formset.forms),
                available_fieldsets.get(id=form.cleaned_data["fieldset"])
                if int(form.cleaned_data.get("fieldset") or 0)
                else None,
            )

            store_settings(
                request.user,
                "data_import_file_%s" % imp.field_hash,
                simplejson.dumps(dict(options=form.cleaned_data, mapping=mapping_formset.cleaned_data)),
            )

            if request.POST.get("import_button"):
                j = JobInfo.objects.create(
                    owner=request.user,
                    func="csvimport",
                    arg=simplejson.dumps(
                        dict(
                            file=os.path.join(_get_scratch_dir(), _get_filename(request, file)),
                            separator=form.cleaned_data["separator"],
                            collections=map(int, form.cleaned_data["collections"]),
                            update=form.cleaned_data["update"],
                            add=form.cleaned_data["add"],
                            test=form.cleaned_data["test"],
                            personal=form.cleaned_data["personal"],
                            fieldset=form.cleaned_data["fieldset"],
                            mapping=dict(
                                (f.cleaned_data["fieldname"], int(f.cleaned_data["mapping"]))
                                for f in mapping_formset.forms
                                if f.cleaned_data["mapping"]
                            ),
                            separate_fields=dict(
                                (f.cleaned_data["fieldname"], f.cleaned_data["separate"]) for f in mapping_formset.forms
                            ),
                            labels=dict(
                                (f.cleaned_data["fieldname"], f.cleaned_data["label"]) for f in mapping_formset.forms
                            ),
                            order=dict(
                                (f.cleaned_data["fieldname"], int(f.cleaned_data["ORDER"]))
                                for f in mapping_formset.forms
                            ),
                            hidden=dict(
                                (f.cleaned_data["fieldname"], f.cleaned_data["hidden"]) for f in mapping_formset.forms
                            ),
                        )
                    ),
                )
                j.run()
                request.user.message_set.create(message="Import job has been submitted.")
                return HttpResponseRedirect("%s?highlight=%s" % (reverse("workers-jobs"), j.id))
        else:
            imp, preview_rows = analyze()
    else:
        imp, preview_rows = analyze()

        # try to load previously stored settings
        key = "data_import_file_%s" % imp.field_hash
        values = load_settings(request.user, key)
        if values.has_key(key):
            value = simplejson.loads(values[key][0])
            mapping = value["mapping"]
            options = value["options"]
        else:
            mapping = [dict(fieldname=f, mapping=v.id if v else 0, separate=True) for f, v in imp.mapping.iteritems()]
            options = None

        mapping = sorted(mapping, key=lambda m: m["fieldname"])

        mapping_formset = MappingFormSet(initial=mapping, prefix="m")
        form = ImportOptionsForm(initial=options)

    return render_to_response(
        "data_import_file.html",
        {
            "form": form,
            "preview_rows": preview_rows,
            "mapping_formset": mapping_formset,
            "writable_collections": bool(writable_collection_ids),
        },
        context_instance=RequestContext(request),
    )
Example #11
0
def import_files(request):

    available_storage = get_list_or_404(filter_by_access(request.user, Storage, write=True).order_by('title'))
    available_collections = get_list_or_404(filter_by_access(request.user, Collection))
    writable_collection_ids = accessible_ids(request.user, Collection, write=True)

    storage_choices = choices = [make_storage_select_choice(s, request.user) for s in available_storage]

    class UploadFileForm(forms.Form):
        collection = forms.ChoiceField(choices=((c.id, '%s%s' % ('*' if c.id in writable_collection_ids else '', c.title)) for c in sorted(available_collections, key=lambda c: c.title)))
        storage = forms.ChoiceField(choices=storage_choices)
        file = forms.FileField()
        create_records = forms.BooleanField(required=False)
        replace_files = forms.BooleanField(required=False, label='Replace files of same type')
        personal_records = forms.BooleanField(required=False)

        def clean(self):
            cleaned_data = self.cleaned_data
            if any(self.errors):
                return cleaned_data
            personal = cleaned_data['personal_records']
            if not personal:
                if not int(cleaned_data['collection']) in writable_collection_ids:
                    self._errors['collection'] = ErrorList(["Can only add personal records to selected collection"])
                    del cleaned_data['collection']
            return cleaned_data


    if request.method == 'POST':

        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():

            create_records = form.cleaned_data['create_records']
            replace_files = form.cleaned_data['replace_files']
            personal_records = form.cleaned_data['personal_records']

            collection = get_object_or_404(filter_by_access(request.user, Collection.objects.filter(id=form.cleaned_data['collection']), write=True if not personal_records else None))
            storage = get_object_or_404(filter_by_access(request.user, Storage.objects.filter(id=form.cleaned_data['storage'].split(',')[0]), write=True))
            file = request.FILES['file']
            record = None

            limit = storage.get_upload_limit(request.user)
            if limit > 0 and file.size > limit * 1024:
                result = "The uploaded file is too large (%d>%d)." % (file.size, limit * 1024)
            else:

                mimetype = mimetypes.guess_type(file.name)[0] or file.content_type

                owner = request.user if personal_records else None
                id = os.path.splitext(file.name)[0]

                # find record by identifier
                titlefield = standardfield('title')
                idfield = standardfield('identifier')
                idfields = standardfield('identifier', equiv=True)

                # Match identifiers that are either full file name (with extension) or just base name match
                records = Record.by_fieldvalue(idfields, (id, file.name)).filter(collection=collection, owner=owner)
                result = "File skipped."

                if len(records) == 1:
                    # Matching record found
                    record = records[0]
                    media = record.media_set.filter(storage=storage, mimetype=mimetype)
                    if len(media) == 0:
                        # No media yet
                        media = Media.objects.create(record=record,
                                                     name=id,
                                                     storage=storage,
                                                     mimetype=mimetype)
                        media.save_file(file.name, file)
                        result = "File added (Identifier '%s')." % id
                    elif replace_files:
                        # Replace existing media
                        media = media[0]
                        media.delete_file()
                        media.save_file(file.name, file)
                        result = "File replaced (Identifier '%s')." % id
                    else:
                        result = "File skipped, media files already attached."
                elif len(records) == 0:
                    # No matching record found
                    if create_records:
                        # Create a record
                        record = Record.objects.create(name=id, owner=owner)
                        CollectionItem.objects.create(collection=collection, record=record)
                        FieldValue.objects.create(record=record, field=idfield, value=id, order=0)
                        FieldValue.objects.create(record=record, field=titlefield, value=id, order=1)
                        media = Media.objects.create(record=record,
                                                     name=id,
                                                     storage=storage,
                                                     mimetype=mimetype)
                        media.save_file(file.name, file)
                        result = "File added to new record (Identifier '%s')." % id
                    else:
                        result = "File skipped, no matching record found (Identifier '%s')." % id
                else:
                    result = "File skipped, multiple matching records found (Identifier '%s')." % id
                    # Multiple matching records found
                    pass

            if request.POST.get('swfupload') == 'true':
                html = render_to_string('storage_import_file_response.html',
                                 {'result': result,
                                  'record': record,},
                                 context_instance=RequestContext(request)
                                 )
                return HttpResponse(content=simplejson.dumps(dict(status='ok', html=html)),
                                    mimetype='application/json')

            request.user.message_set.create(message=result)
            next = request.GET.get('next', request.get_full_path())
            return HttpResponseRedirect(next)

        else:
            # invalid form submission
            if request.POST.get('swfupload') == 'true':
                html = render_to_string('storage_import_file_response.html',
                                 {'result': form.errors},
                                 context_instance=RequestContext(request)
                                 )
                return HttpResponse(content=simplejson.dumps(dict(status='ok', html=html)),
                                    mimetype='application/json')

    else:
        form = UploadFileForm()

    return render_to_response('storage_import_files.html',
                              {'upload_form': form,
                               },
                              context_instance=RequestContext(request))
Example #12
0
def record(request, id, name, contexttype=None, contextid=None, contextname=None,
           edit=False, customize=False, personal=False):

    writable_collections = list(accessible_ids(request.user, Collection, write=True))
    readable_collections = list(accessible_ids(request.user, Collection))
    can_edit = request.user.is_authenticated()

    if id and name:
        record = Record.get_or_404(id, request.user)
        can_edit = can_edit and record.editable_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()

    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 id and name:
        fieldset = None
    else:
        # Creating new record, use DC fieldset by default
        fieldset = FieldSet.objects.get(name='dc')

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

    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,
                               'next': request.GET.get('next'),
                               'collection_items': collection_items,
                               'upload_form': upload_form,
                               'upload_url': (reverse('storage-media-upload', args=(record.id, record.name)) + "?sidebar")
                                             if record.id else None,
                               },
                              context_instance=RequestContext(request))
Example #13
0
def manage_collection(request, id=None, name=None):

    if id and name:
        collection = get_object_or_404(Collection,
                                       id__in=accessible_ids(request.user, Collection, manage=True),
                                       id=id)
    else:
        collection = Collection(title='Untitled')
        if not request.user.is_superuser:
            collection.owner = request.user
            collection.hidden = True

    class CollectionForm(forms.ModelForm):

        class UserField(forms.CharField):

            widget=forms.TextInput(attrs={'class': 'autocomplete-user'})

            def prepare_value(self, value):
                try:
                    if not value or getattr(self, "_invalid_user", False):
                        return value
                    return User.objects.get(id=value).username
                except ValueError:
                    return value
                except ObjectDoesNotExist:
                    return None

            def to_python(self, value):
                try:
                    return User.objects.get(username=value) if value else None
                except ObjectDoesNotExist:
                    self._invalid_user = True
                    raise ValidationError('User not found')


        children = forms.ModelMultipleChoiceField(queryset=filter_by_access(request.user, Collection).exclude(id=collection.id),
                                                  widget=forms.CheckboxSelectMultiple,
                                                  required=False)
        owner = UserField(widget=None if request.user.is_superuser else forms.HiddenInput, required=False)

        def clean_owner(self):
            if not request.user.is_superuser:
                # non-admins cannot change collection owner
                return collection.owner
            else:
                return self.cleaned_data['owner']

        class Meta:
            model = Collection
            fields = ('title', 'hidden', 'owner', 'description', 'agreement', 'children')

    if request.method == "POST":
        if request.POST.get('delete-collection'):
            if not (request.user.is_superuser or request.user == collection.owner):
                raise HttpResponseForbidden()
            request.user.message_set.create(message="Collection '%s' has been deleted." % collection.title)
            collection.delete()
            return HttpResponseRedirect(reverse('data-collections-manage'))
        else:
            form = CollectionForm(request.POST, instance=collection)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect(reverse('data-collection-manage', kwargs=dict(
                    id=form.instance.id, name=form.instance.name)))
    else:
        form = CollectionForm(instance=collection)

    return render_to_response('data_collection_edit.html',
                          {'form': form,
                           'collection': collection,
                           'can_delete': collection.id and (request.user.is_superuser or collection.owner == request.user),
                          },
                          context_instance=RequestContext(request))
Example #14
0
def data_import_file(request, file):

    available_collections = filter_by_access(request.user, Collection)
    writable_collection_ids = accessible_ids(request.user, Collection, write=True)
    if not available_collections:
        raise Http404
    available_fieldsets = FieldSet.for_user(request.user)

    def _get_fields():
        return Field.objects.select_related('standard').all().order_by('standard', '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


    #def _field_choices():
    #    grouped = {}
    #    for f in _get_fields():
    #        grouped.setdefault(f.standard and f.standard.title or 'Other', []).append(f)
    #    return [('0', '[do not import]'), ('-1', '[new field]')] + \
    #           [(g, [(f.id, f.label) for f in grouped[g]]) for g in grouped]

    class ImportOptionsForm(forms.Form):
        separator = forms.CharField(required=False)
        collections = forms.MultipleChoiceField(choices=((c.id, '%s%s' % ('*' if c.id in writable_collection_ids else '', c.title)) for c in sorted(available_collections, key=lambda c: c.title)),
                                                widget=forms.CheckboxSelectMultiple)
        fieldset = FieldSetChoiceField(user=request.user, default_label='any')
        #forms.ChoiceField(choices=[(0, 'any')] + [(f.id, f.title) for f in available_fieldsets], required=False)
        update = forms.BooleanField(label='Update existing records', initial=True, required=False)
        add = forms.BooleanField(label='Add new records', initial=True, required=False)
        test = forms.BooleanField(label='Test import only', initial=False, required=False)
        personal = forms.BooleanField(label='Personal records', initial=True, required=False)

        def clean(self):
            cleaned_data = self.cleaned_data
            if any(self.errors):
                return cleaned_data
            personal = cleaned_data['personal']
            if not personal:
                for c in map(int, cleaned_data['collections']):
                    if not c in writable_collection_ids:
                        self._errors['collections'] = ErrorList(["Can only add personal records to selected collections"])
                        del cleaned_data['collections']
                        return cleaned_data
            return cleaned_data

    class MappingForm(forms.Form):
        fieldname = forms.CharField(widget=DisplayOnlyTextWidget, required=False)
        mapping = forms.ChoiceField(choices=_field_choices(), required=False)
        separate = forms.BooleanField(required=False)
        label = forms.CharField(required=False)
        hidden = forms.BooleanField(required=False)

    class BaseMappingFormSet(forms.formsets.BaseFormSet):
        def clean(self):
            if any(self.errors):
                return
            _dcidentifier = Field.objects.get(name='identifier', standard__prefix='dc')
            _identifier_ids = list(_dcidentifier.get_equivalent_fields().values_list('id', flat=True)) + [_dcidentifier.id]
            for i in range(self.total_form_count()):
                if self.forms[i].cleaned_data['mapping'] and \
                    (int(self.forms[i].cleaned_data['mapping']) in _identifier_ids):
                    return
            raise forms.ValidationError, "At least one field must be mapped to an identifier field."


    MappingFormSet = formset_factory(MappingForm, extra=0, formset=BaseMappingFormSet, can_order=True)

    def analyze(collections=None, separator=None, separate_fields=None, fieldset=None):
        try:
            with open(os.path.join(_get_scratch_dir(), _get_filename(request, file)), 'rU') as csvfile:
                imp = SpreadsheetImport(csvfile, collections, separator=separator,
                                        separate_fields=separate_fields, preferred_fieldset=fieldset)
                return imp, imp.analyze()
        except IOError:
            raise Http404()

    if request.method == 'POST':
        form = ImportOptionsForm(request.POST)
        mapping_formset = MappingFormSet(request.POST, prefix='m')
        if form.is_valid() and mapping_formset.is_valid():

            imp, preview_rows = analyze(available_collections.filter(id__in=form.cleaned_data['collections']),
                       form.cleaned_data['separator'],
                       dict((f.cleaned_data['fieldname'], f.cleaned_data['separate'])
                            for f in mapping_formset.forms),
                       available_fieldsets.get(id=form.cleaned_data['fieldset']) if int(form.cleaned_data.get('fieldset') or 0) else None)

            store_settings(request.user,
                           'data_import_file_%s' % imp.field_hash,
                           simplejson.dumps(dict(options=form.cleaned_data, mapping=mapping_formset.cleaned_data)))

            if request.POST.get('import_button'):
                j = JobInfo.objects.create(owner=request.user,
                                       func='csvimport',
                                       arg=simplejson.dumps(dict(
                                                file=_get_filename(request, file),
                                                separator=form.cleaned_data['separator'],
                                                collections=map(int, form.cleaned_data['collections']),
                                                update=form.cleaned_data['update'],
                                                add=form.cleaned_data['add'],
                                                test=form.cleaned_data['test'],
                                                personal=form.cleaned_data['personal'],
                                                fieldset=form.cleaned_data['fieldset'],
                                                mapping=dict((f.cleaned_data['fieldname'], int(f.cleaned_data['mapping']))
                                                             for f in mapping_formset.forms if f.cleaned_data['mapping']),
                                                separate_fields=dict((f.cleaned_data['fieldname'], f.cleaned_data['separate'])
                                                                     for f in mapping_formset.forms),
                                                labels=dict((f.cleaned_data['fieldname'], f.cleaned_data['label'])
                                                             for f in mapping_formset.forms),
                                                order=dict((f.cleaned_data['fieldname'], int(f.cleaned_data['ORDER']))
                                                             for f in mapping_formset.forms),
                                                hidden=dict((f.cleaned_data['fieldname'], f.cleaned_data['hidden'])
                                                             for f in mapping_formset.forms),
                                                )
                                       ))
                j.run()
                request.user.message_set.create(message='Import job has been submitted.')
                return HttpResponseRedirect("%s?highlight=%s" % (reverse('workers-jobs'), j.id))
        else:
            imp, preview_rows = analyze()
    else:
        imp, preview_rows = analyze()

        # try to load previously stored settings
        key = 'data_import_file_%s' % imp.field_hash
        values = load_settings(request.user, key)
        if values.has_key(key):
            value = simplejson.loads(values[key][0])
            mapping = value['mapping']
            options = value['options']
        else:
            mapping = [dict(fieldname=f, mapping=v.id if v else 0, separate=True)
                       for f, v in imp.mapping.iteritems()]
            options = None

        mapping = sorted(mapping, key=lambda m: m['fieldname'])

        mapping_formset = MappingFormSet(initial=mapping, prefix='m')
        form = ImportOptionsForm(initial=options)

    return render_to_response('data_import_file.html',
                              {'form': form,
                               'preview_rows': preview_rows,
                               'mapping_formset': mapping_formset,
                               'writable_collections': bool(writable_collection_ids),
                              },
                              context_instance=RequestContext(request))
Example #15
0
def edit(request, id, name):

    presentation = get_object_or_404(Presentation.objects.filter(
        id=id, id__in=accessible_ids(request.user, Presentation, write=True, manage=True)))
    existing_tags = [t.name for t in Tag.objects.usage_for_model(
        OwnedWrapper, filters=dict(user=request.user, content_type=OwnedWrapper.t(Presentation)))]
    tags = Tag.objects.get_for_object(
        OwnedWrapper.objects.get_for_object(user=request.user, object=presentation))

    class PropertiesForm(forms.Form):
        title = forms.CharField(label='Title', max_length=Presentation._meta.get_field('title').max_length)
#        tags = SplitTaggingField(label='Tags', choices=[(t, t) for t in existing_tags],
#                                         required=False, add_label='Additional tags')
        hidden = forms.BooleanField(label='Hidden', required=False)
        description = forms.CharField(label='Description',
                                      widget=forms.Textarea(attrs={'rows': 5}), required=False)
        password = forms.CharField(label='Password', required=False,
                                   max_length=Presentation._meta.get_field('password').max_length)
        fieldset = FieldSetChoiceField(label='Field set', user=presentation.owner)
        hide_default_data = forms.BooleanField(label='Hide default data', required=False)


    class BaseOrderingForm(ModelForm):
        record = forms.CharField(widget=forms.HiddenInput)
        annotation = forms.CharField(widget=forms.Textarea, required=False)

        def __init__(self, initial=None, instance=None, *args, **kwargs):
            if instance:
                object_data = dict(annotation=instance.annotation)
            else:
                object_data = dict()
            if initial is not None:
                object_data.update(initial)
            super(BaseOrderingForm, self).__init__(initial=object_data, instance=instance, *args, **kwargs)

        def clean_record(self):
            return Record.objects.get(id=self.cleaned_data['record'])

        def save(self, commit=True):
            instance = super(BaseOrderingForm, self).save(commit)
            instance.annotation = self.cleaned_data['annotation']
            return instance

    self_page = HttpResponseRedirect(
        reverse('presentation-edit', kwargs={'id': presentation.id, 'name': presentation.name}))

    OrderingFormSet = modelformset_factory(PresentationItem, extra=0, can_delete=True,
                                           exclude=('presentation'), form=BaseOrderingForm)
    queryset = presentation.items.select_related('record', 'presentation', 'presentation__owner').all()
    if request.method == 'POST' and request.POST.get('update-items'):
        formset = OrderingFormSet(request.POST, queryset=queryset)
        if formset.is_valid():
            instances = formset.save(commit=False)
            for instance in instances:
                instance.presentation = presentation
                instance.save()
            request.user.message_set.create(message="Changes to presentation items saved successfully.")
            return self_page
    else:
        formset = OrderingFormSet(queryset=queryset)

    if request.method == 'POST' and request.POST.get('add-selected-items'):
        add_selected_items(request, presentation)
        return self_page

    if request.method == "POST" and request.POST.get('update-properties'):

        update_actionbar_tags(request, presentation)

        form = PropertiesForm(request.POST)
        if form.is_valid():
            presentation.title = form.cleaned_data['title']
            presentation.name = None
            if presentation.owner.has_perm('presentation.publish_presentations'):
                presentation.hidden = form.cleaned_data['hidden']
            presentation.description = form.cleaned_data['description']
            presentation.password = form.cleaned_data['password']
            presentation.fieldset = FieldSet.for_user(presentation.owner).get(id=form.cleaned_data['fieldset']) if form.cleaned_data['fieldset'] else None
            presentation.hide_default_data = form.cleaned_data['hide_default_data']
            presentation.save()
            request.user.message_set.create(message="Changes to presentation saved successfully.")
            return self_page
    else:
        form = PropertiesForm(initial={'title': presentation.title,
                               'hidden': presentation.hidden,
                               'description': presentation.description,
                               'hidden': presentation.hidden,
                               'fieldset': presentation.fieldset.id if presentation.fieldset else None,
                               'hide_default_data': presentation.hide_default_data,
                               })

    contenttype = ContentType.objects.get_for_model(Presentation)
    return render_to_response('presentation_properties.html',
                      {'presentation': presentation,
                       'contenttype': "%s.%s" % (contenttype.app_label, contenttype.model),
                       'formset': formset,
                       'form': form,
                       'selected_tags': [tag.name for tag in tags],
                       'usertags': existing_tags if len(existing_tags) > 0 else None,
                       },
                      context_instance=RequestContext(request))
Example #16
0
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),
    )
Example #17
0
def browse(request, manage=False):

    if manage and not request.user.is_authenticated():
        raise Http404()

    presenter = request.GET.get('presenter')
    tags = filter(None, request.GET.getlist('t'))
    remove_tag = request.GET.get('rt')
    if remove_tag and remove_tag in tags:
        tags.remove(remove_tag)
    keywords = request.GET.get('kw', '')
    get = request.GET.copy()
    get.setlist('t', tags)
    if get.has_key('rt'):
        del get['rt']

    if request.user.is_authenticated():
        existing_tags = Tag.objects.usage_for_model(OwnedWrapper,
                        filters=dict(user=request.user, content_type=OwnedWrapper.t(Presentation)))
    else:
        existing_tags = ()

    if tags:
        qs = OwnedWrapper.objects.filter(content_type=OwnedWrapper.t(Presentation))
        # get list of matching IDs for each individual tag, since tags may be attached by different owners
        ids = [list(TaggedItem.objects.get_by_model(qs, '"%s"' % tag).values_list('object_id', flat=True)) for tag in tags]
        q = Q(*(Q(id__in=x) for x in ids))
    else:
        q = Q()

    if presenter:
        presenter = User.objects.get(username=presenter)
        qp = Q(owner=presenter)
    else:
        qp = Q()

    if keywords:
        qk = Q(*(Q(title__icontains=kw) | Q(description__icontains=kw) |
                 Q(owner__last_name__icontains=kw) | Q(owner__first_name__icontains=kw) |
                 Q(owner__username__icontains=kw) for kw in keywords.split()))
    else:
        qk = Q()

    if manage:
        qv = Q()
        qid = Q(id__in=accessible_ids(request.user, Presentation, write=True, manage=True))
    else:
        qv = Presentation.published_Q()
        qid = Q(id__in=accessible_ids(request.user, Presentation))

    presentations = Presentation.objects.select_related('owner').filter(q, qp, qk, qv, qid).order_by('title')

    if request.method == "POST":

        if manage and (request.POST.get('hide') or request.POST.get('unhide')) and request.user.has_perm('presentation.publish_presentations'):
            hide = request.POST.get('hide') or False
            ids = map(int, request.POST.getlist('h'))
            for presentation in Presentation.objects.filter(owner=request.user, id__in=ids):
                presentation.hidden = hide
                presentation.save()

        if manage and request.POST.get('delete'):
            ids = map(int, request.POST.getlist('h'))
            Presentation.objects.filter(owner=request.user, id__in=ids).delete()

        get['kw'] = request.POST.get('kw') or keywords

        if request.POST.get('update_tags'):
            ids = map(int, request.POST.getlist('h'))
            update_actionbar_tags(request, *presentations.filter(id__in=ids))

        # check for clicks on "add selected items" buttons
        for button in filter(lambda k: k.startswith('add-selected-items-'), request.POST.keys()):
            id = int(button[len('add-selected-items-'):])
            presentation = get_object_or_404(Presentation.objects.filter(
                id=id, id__in=accessible_ids(request.user, Presentation, write=True, manage=True)))
            add_selected_items(request, presentation)
            return HttpResponseRedirect(reverse('presentation-edit', args=(presentation.id, presentation.name)))

        return HttpResponseRedirect(request.path + '?' + get.urlencode())


    active_tags = tags
    active_presenter = presenter

    def col(model, field):
        qn = backend.DatabaseOperations().quote_name
        return '%s.%s' % (qn(model._meta.db_table), qn(model._meta.get_field(field).column))

    if presentations and not manage:
        q = OwnedWrapper.objects.extra(
            tables=(Presentation._meta.db_table,),
            where=('%s=%s' % (col(OwnedWrapper, 'object_id'), col(Presentation, 'id')),
                   '%s=%s' % (col(OwnedWrapper, 'user'), col(Presentation, 'owner')))).filter(
            object_id__in=presentations.values('id'),
            content_type=OwnedWrapper.t(Presentation))
        tags = Tag.objects.usage_for_queryset(q, counts=True)

        for p in presentations:
            p.verify_password(request)
    else:
        tags = ()

    if presentations and request.user.is_authenticated():
        usertags = Tag.objects.usage_for_queryset(OwnedWrapper.objects.filter(
                        user=request.user,
                        object_id__in=presentations.values('id'),
                        content_type=OwnedWrapper.t(Presentation)), counts=True)
    else:
        usertags = ()

    presenters = User.objects.filter(presentation__in=presentations) \
                     .annotate(presentations=Count('presentation')).order_by('last_name', 'first_name')

    return render_to_response('presentation_browse.html',
                          {'manage': manage,
                           'tags': tags if len(tags) > 0 else None,
                           'usertags': usertags if len(usertags) > 0 else None,
                           'active_tags': active_tags,
                           'active_presenter': presenter,
                           'presentations': presentations,
                           'presenters': presenters if len(presenters) > 1 else None,
                           'keywords': keywords,
                           },
                          context_instance=RequestContext(request))
Example #18
0
 def get_by_id_for_request(id, request):
     p = Presentation.objects.filter(Presentation.published_Q(request.user),
                                     id=id,
                                     id__in=accessible_ids(request.user, Presentation))
     return p[0] if p and p[0].verify_password(request) else None
Example #19
0
 def editable_by(self, user):
     return (
         # checks if user is owner:
         check_access(user, self, write=True) or
         # or if user has write access to collection:
         len(accessible_ids(user, self.collection_set, write=True)) > 0)
Example #20
0
def duplicate(request, id, name):
    presentation = get_object_or_404(Presentation.objects.filter(
        id=id, id__in=accessible_ids(request.user, Presentation, write=True, manage=True)))
    dup = duplicate_presentation(presentation, request.user)
    return HttpResponseRedirect(reverse('presentation-edit',
                                        args=(dup.id, dup.name)))