예제 #1
0
def get_batch_parents_batches_list(request, bat_id):
    results_per_page = int_arg(request.GET.get('more', 30))
    cursor = request.GET.get('cursor')
    limit = results_per_page

    parent_batch = get_object_or_404(Batch, id=int(bat_id))

    # check permission on accession object
    perms = get_permissions_for(request.user,
                                parent_batch.accession.content_type.app_label,
                                parent_batch.accession.content_type.model,
                                parent_batch.accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(
            _('Invalid permission to access to this accession'))

    if cursor:
        cursor = json.loads(cursor)
        cursor_name, cursor_id = cursor
        batches = parent_batch.batches.filter(Q(name__gt=cursor_name))
    else:
        batches = parent_batch.batches.all()

    batches = batches.order_by('name')[:limit]

    items_list = []

    for batch in batches:
        b = {
            'id': batch.pk,
            'name': batch.name,
            'accession': batch.accession_id,
            'layout': batch.layout_id,
            'descriptors': batch.descriptors,
            'location': batch.location
        }

        items_list.append(b)

    if len(items_list) > 0:
        # prev cursor (asc order)
        obj = items_list[0]
        prev_cursor = (obj['name'], obj['id'])

        # next cursor (asc order)
        obj = items_list[-1]
        next_cursor = (obj['name'], obj['id'])
    else:
        prev_cursor = None
        next_cursor = None

    results = {
        'perms': [],
        'items': items_list,
        'prev': prev_cursor,
        'cursor': cursor,
        'next': next_cursor,
    }

    return HttpResponseRest(request, results)
예제 #2
0
def get_media(request, uuid):
    """
    Returns the media details (mime-type, file name, size...) but not the file content.
    """
    media = get_object_or_404(Media, uuid=uuid)

    # check user permission on the media
    if media.owner_content_type == "auth.user":
        if media.owner_object_id != request.user.pk:
            raise PermissionDenied(_('Your are not the owner of the media'))
    else:
        perms = get_permissions_for(request.user,
                                    media.owner_content_type.app_label,
                                    media.owner_content_type.model,
                                    media.owner_object_id)
        if len(perms) == 0:
            raise PermissionDenied(_('No permissions to the owner entity'))

    result = {
        'id': media.pk,
        'uuid': media.uuid,
        'name': media.name,
        'created_date': media.created_date,
        'modified_date': media.modified_date,
        'file_name': media.file_name,
        'file_size': media.file_size,
        'mime_type': media.mime_type
    }

    return HttpResponseRest(request, result)
예제 #3
0
def accession_batches_list_count(request, acc_id):
    accession = get_object_or_404(Accession, id=int(acc_id))

    # check permission on accession object
    perms = get_permissions_for(request.user, accession.content_type.app_label,
                                accession.content_type.model, accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(
            _('Invalid permission to access to this accession'))

    from main.cursor import CursorQuery
    cq = CursorQuery(Batch)

    if request.GET.get('search'):
        search = json.loads(request.GET['search'])
        cq.filter(search)

    if request.GET.get('filters'):
        filters = json.loads(request.GET['filters'])
        cq.filter(filters)

    cq.filter(accession=accession.id)

    count = cq.count()

    results = {'count': count}

    return HttpResponseRest(request, results)
예제 #4
0
def get_location_details_json(request, location_id):
    """
    Get the details of a storage location.
    """

    location = StorageLocation.objects.get(id=int(location_id))

    # check permission on this object
    perms = get_permissions_for(request.user, location.content_type.app_label, location.content_type.model, location.pk)
    if 'accession.get_location' not in perms:
        raise PermissionDenied(_('Invalid permission to access to this storage location'))

    children = []

    for child in location.children.all():
        children.append({
            'id': child.id,
            'name': child.name,
            'label': child.get_label()
        })

    result = {
        'id': location.id,
        'name': location.name,
        'label': location.get_label(),
        'parent': {
            'id': location.parent.id,
            'name': location.parent.name,
            'label': location.parent.get_label(),
        },
        'children': children
    }

    return HttpResponseRest(request, result)
예제 #5
0
def create_storage_location(request, location_id):
    """
    Modify a storage location.
    """
    storage_location = StorageLocation.objects.get(id=int(location_id))

    # check permission on this object
    perms = get_permissions_for(request.user, storage_location.content_type.app_label,
                                storage_location.content_type.model, storage_location.pk)
    if 'accession.get_location' not in perms:
        raise PermissionDenied(_('Invalid permission to access to this storage location'))

    name = request.data['name']
    label = request.data['label']

    if isinstance(request.data['parent_storage_location'], int):
        parent_storage_location = StorageLocation.objects.get(id=request.data['parent_storage_location'])
    else:
        parent_storage_location = None

    lang = translation.get_language()

    storage_location.name = name
    storage_location.set_label(lang, label)
    storage_location.parent = parent_storage_location

    result = {
        'id': storage_location.id,
        'name': storage_location.name,
        'label': storage_location.get_label()
    }

    return HttpResponseRest(request, result)
예제 #6
0
def accession_batches_list(request, acc_id):
    results_per_page = int_arg(request.GET.get('more', 30))
    cursor = json.loads(request.GET.get('cursor', 'null'))
    limit = results_per_page
    sort_by = json.loads(request.GET.get('sort_by', '[]'))

    accession = get_object_or_404(Accession, id=int(acc_id))

    # check permission on accession object
    perms = get_permissions_for(request.user, accession.content_type.app_label,
                                accession.content_type.model, accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(
            _('Invalid permission to access to this accession'))

    if not len(sort_by) or sort_by[-1] not in ('id', '+id', '-id'):
        order_by = sort_by + ['id']
    else:
        order_by = sort_by

    from main.cursor import CursorQuery
    cq = CursorQuery(Batch)

    if request.GET.get('search'):
        search = json.loads(request.GET['search'])
        cq.filter(search)

    if request.GET.get('filters'):
        filters = json.loads(request.GET['filters'])
        cq.filter(filters)

    cq.filter(accession=accession.id)
    cq.cursor(cursor, order_by)
    cq.order_by(order_by).limit(limit)

    batch_list = []

    for batch in cq:
        a = {
            'id': batch.pk,
            'name': batch.name,
            'accession': batch.accession_id,
            'layout': batch.layout_id,
            'descriptors': batch.descriptors
        }

        batch_list.append(a)

    results = {
        'perms': [],
        'items': batch_list,
        'prev': cq.prev_cursor,
        'cursor': cursor,
        'next': cq.next_cursor,
    }

    return HttpResponseRest(request, results)
예제 #7
0
def change_accession_id_classification_entry(request, acc_id):
    """
    Remove a secondary classification from an accession
    """
    action = request.data['action']
    target = request.data['target']

    accession = get_object_or_404(Accession, id=int(acc_id))

    # check permission on this object
    perms = get_permissions_for(request.user, accession.content_type.app_label, accession.content_type.model,
                                accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(_('Invalid permission to access to this accession'))

    if target == "classification_entry":
        classification_entry_id = int_arg(request.data['classification_entry'])

        if action == "add":
            if not request.user.has_perm('accession.add_accessionclassificationentry'):
                raise PermissionDenied(_("You are not allowed to add an entry of classification to an accession"))

            if classification_entry_id == accession.primary_classification_entry_id:
                raise SuspiciousOperation(_('Already defined as primary classification'))

            classification_entry = get_object_or_404(ClassificationEntry, id=classification_entry_id)

            if AccessionClassificationEntry.objects.filter(accession=accession, classification_entry=classification_entry).exists():
                raise SuspiciousOperation(_('It is not permit to add twice the same classification entry'))

            AccessionClassificationEntry.objects.create(
                accession=accession, classification_entry=classification_entry, primary=False)

        elif action == "remove":
            if not request.user.has_perm('accession.delete_accessionclassificationentry'):
                raise PermissionDenied(_("You are not allowed to remove an entry of classification from an accession"))

            if classification_entry_id == accession.primary_classification_entry:
                raise SuspiciousOperation(_('It is not permit to remove the primary classification entry'))

            AccessionClassificationEntry.objects.filter(
                accession=accession, classification_entry_id=classification_entry_id).delete()
        else:
            raise SuspiciousOperation('Invalid action')

    return HttpResponseRest(request, {})
예제 #8
0
def patch_batch(request, bat_id):
    batch = get_object_or_404(Batch, id=int(bat_id))

    # check permission on accession object
    perms = get_permissions_for(request.user,
                                batch.accession.content_type.app_label,
                                batch.accession.content_type.model,
                                batch.accession.pk)
    if 'accession.change_accession' not in perms:
        raise PermissionDenied(
            _('Invalid permission to modify this accession'))

    entity_status = request.data.get("entity_status")
    descriptors = request.data.get("descriptors")

    result = {'id': batch.id}

    try:
        with transaction.atomic():
            if entity_status is not None and batch.entity_status != entity_status:
                batch.set_status(entity_status)
                result['entity_status'] = entity_status
                batch.update_field('entity_status')

            if descriptors is not None:
                # update descriptors
                descriptors_builder = DescriptorsBuilder(batch)

                descriptors_builder.check_and_update(batch.layout, descriptors)

                batch.descriptors = descriptors_builder.descriptors
                result['descriptors'] = batch.descriptors

                descriptors_builder.update_associations()

                batch.update_descriptors(
                    descriptors_builder.changed_descriptors())
                batch.update_field('descriptors')

                batch.save()
    except IntegrityError as e:
        logger.error(repr(e))
        raise SuspiciousOperation(_("Unable to update the batch"))

    return HttpResponseRest(request, result)
예제 #9
0
def get_accession_details_json(request, acc_id):
    """
    Get the details of an accession.
    """

    accession = Accession.objects.get(id=int(acc_id))

    # check permission on this object
    perms = get_permissions_for(request.user, accession.content_type.app_label,
                                accession.content_type.model, accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(
            _('Invalid permission to access to this accession'))

    result = {
        'id': accession.id,
        'name': accession.name,
        'code': accession.code,
        'primary_classification_entry':
        accession.primary_classification_entry_id,
        'synonyms': [],
        'layout': accession.layout_id,
        'descriptors': accession.descriptors,
        'panels': []
    }

    for panel in accession.panels.all():
        result['panels'].append({
            'id': panel.id,
            'name': panel.name,
            'layout': panel.layout.pk if panel.layout else None,
            'descriptors': panel.descriptors,
            'accessions_amount': panel.accessions.count()
        })

    for s in AccessionSynonym.objects.filter(entity=accession.id).order_by(
            'synonym_type', 'language'):
        result['synonyms'].append({
            'id': s.id,
            'name': s.name,
            'synonym_type': s.synonym_type_id,
            'language': s.language,
        })

    return HttpResponseRest(request, result)
예제 #10
0
def get_batch_details_json(request, bat_id):
    """
    Get the details of a batch.
    """
    batch = Batch.objects.get(id=int(bat_id))

    # check permission on this object
    perms = get_permissions_for(request.user, batch.content_type.app_label,
                                batch.content_type.model, batch.pk)
    if 'accession.get_batch' not in perms:
        raise PermissionDenied(_('Invalid permission to access to this batch'))

    result = {
        'id': batch.id,
        'name': batch.name,
        'accession': batch.accession_id,
        'layout': batch.layout_id,
        'descriptors': batch.descriptors
    }

    return HttpResponseRest(request, result)
예제 #11
0
def get_batch_parents_batches_list_count(request, bat_id):
    cursor = request.GET.get('cursor')
    parent_batch = get_object_or_404(Batch, id=int(bat_id))

    # check permission on accession object
    perms = get_permissions_for(request.user,
                                parent_batch.accession.content_type.app_label,
                                parent_batch.accession.content_type.model,
                                parent_batch.accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(
            _('Invalid permission to access to this accession'))

    if cursor:
        cursor = json.loads(cursor)
        cursor_name, cursor_id = cursor
        batches = parent_batch.batches.filter(Q(name__gt=cursor_name))
    else:
        batches = parent_batch.batches.all()

    results = {'count': batches.count()}

    return HttpResponseRest(request, results)
예제 #12
0
def download_media_content(request, uuid):
    """
    Download the content of a file using its UUID.
    @see https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/
    @see https://bitbucket.org/renlinx007/django-fileprovider project for example
    """
    media = get_object_or_404(Media, uuid=uuid)

    # check user permission on the media
    if media.owner_content_type == "auth.user":
        if media.owner_object_id != request.user.pk:
            raise PermissionDenied(_('Your are not the owner of the media'))
    else:
        perms = get_permissions_for(request.user,
                                    media.owner_content_type.app_label,
                                    media.owner_content_type.model,
                                    media.owner_object_id)
        if len(perms) == 0:
            raise PermissionDenied(_('No permissions to the owner entity'))

    if settings.DEBUG:
        abs_filename = os.path.join(localsettings.storage_path, media.name)
        local_file = open(abs_filename, "rb")

        # response = HttpResponse(content_type=media.mime_type)
        # response['Content-Disposition'] = 'attachment; filename="' + media.file_name + '"'
        # response.content = local_file

        response = StreamingHttpResponse(local_file, content_type=media.mime_type)
        response['Content-Disposition'] = 'attachment; filename="' + media.file_name + '"'
        response['Content-Length'] = media.file_size
    else:
        response = HttpResponse(content_type=media.mime_type)
        response['Content-Disposition'] = 'attachment; filename="' + media.file_name + '"'
        response['X-Accel-Redirect'] = "{0}/{1}".format(localsettings.storage_location, media.name)

    return response
예제 #13
0
def get_accession_id_classification_entry_list(request, acc_id):
    """
    Get a list of classification for an accession in JSON
    """
    sort_by = json.loads(request.GET.get('sort_by', '[]'))
    accession = get_object_or_404(Accession, id=int(acc_id))

    # check permission on this object
    perms = get_permissions_for(request.user, accession.content_type.app_label, accession.content_type.model,
                                accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(_('Invalid permission to access to this accession'))

    if not len(sort_by) or sort_by[-1] not in ('id', '+id', '-id'):
        order_by = sort_by + ['id']
    else:
        order_by = sort_by

    cq = CursorQuery(ClassificationEntry)

    cq.inner_join(
        ClassificationEntry,
        related_name='accession_set',
        to_related_name='classification_entry',
        accession=accession.pk)

    if request.GET.get('search'):
        cq.filter(json.loads(request.GET['search']))

    if request.GET.get('filters'):
        cq.filter(json.loads(request.GET['filters']))

    cq.prefetch_related(Prefetch(
        "synonyms",
        queryset=ClassificationEntrySynonym.objects.all().order_by('synonym_type', 'language')))

    cq.order_by(order_by)

    classification_entry_items = []

    for classification_entry in cq:
        c = {
            'id': classification_entry.id,
            'name': classification_entry.name,
            'parent': classification_entry.parent_id,
            'rank': classification_entry.rank_id,
            'layout': classification_entry.layout_id,
            'descriptors': classification_entry.descriptors,
            'parent_list': classification_entry.parent_list,
            'synonyms': []
        }

        for synonym in classification_entry.synonyms.all():
            c['synonyms'].append({
                'id': synonym.id,
                'name': synonym.name,
                'synonym_type': synonym.synonym_type_id,
                'language': synonym.language
            })

        classification_entry_items.append(c)

    results = {
        'perms': [],
        'items': classification_entry_items
    }

    return HttpResponseRest(request, results)
예제 #14
0
def update_upload_media(request, uuid):
    """
    Upload a media file from multi-part HTTP file request.
    """
    if not request.FILES:
        raise SuspiciousOperation(_("No file specified"))

    up = request.FILES['file']

    # check file size
    if up.size > localsettings.max_file_size:
        SuspiciousOperation(_("Upload file size limit is set to %i bytes") % localsettings.max_file_size)

    # simple check mime-types using the file extension (can process a test using libmagic)
    guessed_mime_type = mimetypes.guess_type(up.name)[0]
    if guessed_mime_type is None:
        SuspiciousOperation(_("Undetermined uploaded file type"))

    media = get_object_or_404(Media, uuid=uuid)

    # check user permission on the media
    if media.owner_content_type == "auth.user":
        if media.owner_object_id != request.user.pk:
            raise PermissionDenied(_('Your are not the owner of the media'))
    else:
        perms = get_permissions_for(request.user,
                                    media.owner_content_type.app_label,
                                    media.owner_content_type.model,
                                    media.owner_object_id)

        if '%s.change_%s' % (media.owner_content_type.app_label, media.owner_content_type.model) not in perms:
            raise PermissionDenied(_('No change permission to the owner entity'))

    version = media.version + 1

    abs_file_name = os.path.join(localsettings.storage_path, media.name)

    if not os.path.isfile(abs_file_name):
        SuspiciousOperation(_("Trying to update a non-existing file"))

    dst_file = open(abs_file_name, "wb")

    # test mime-type with a buffer of a least 1024 bytes
    test_mime_buffer = io.BytesIO()

    # copy file content
    for chunk in up.chunks():
        dst_file.write(chunk)

        if test_mime_buffer.tell() < 1024:
            test_mime_buffer.write(chunk)

    dst_file.close()

    guessed_mime_type = magic.from_buffer(test_mime_buffer.getvalue(), mime=True)

    # 0660 on file
    os.chmod(abs_file_name, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP)

    # upgrade the version number and file size
    media.version = version
    media.file_size = up.size
    media.mime_type = guessed_mime_type  # up.content_type

    # update the model once file is correctly saved
    media.save()

    result = {
        'id': media.id,
        'uuid': media.uuid,
        'version': media.version,
        'mime_type': media.content_type,
        'file_size': media.file_size,
        'modified_date': media.modified_date
    }

    return HttpResponseRest(request, result)
예제 #15
0
def search_batches_for_accession(request, acc_id):
    """
    Quick search for batches with a exact or partial name.
    """
    filters = json.loads(request.GET['filters'])

    results_per_page = int_arg(request.GET.get('more', 30))
    cursor = request.GET.get('cursor')
    limit = results_per_page

    accession = get_object_or_404(Accession, id=int(acc_id))

    # check permission on accession object
    perms = get_permissions_for(request.user, accession.content_type.app_label,
                                accession.content_type.model, accession.pk)
    if 'accession.get_accession' not in perms:
        raise PermissionDenied(
            _('Invalid permission to access to this accession'))

    if cursor:
        cursor = json.loads(cursor)
        cursor_name, cursor_id = cursor
        batches = accession.batches.filter(Q(name__gt=cursor_name))
    else:
        batches = accession.batches.all()

    if 'name' in filters['fields']:
        name_method = filters.get('method', 'ieq')

        if name_method == 'ieq':
            batches = batches.filter(name__iexact=filters['name'])
        elif name_method == 'icontains':
            batches = batches.filter(name__icontains=filters['name'])

    batches = batches.order_by('name')[:limit]

    items_list = []

    for batch in batches:
        b = {
            'id': batch.pk,
            'name': batch.name,
            'accession': accession.id,
            'layout': batch.layout_id,
            'descriptors': batch.descriptors
        }

        items_list.append(b)

    if len(items_list) > 0:
        # prev cursor (asc order)
        obj = items_list[0]
        prev_cursor = (obj['name'], obj['id'])

        # next cursor (asc order)
        obj = items_list[-1]
        next_cursor = (obj['name'], obj['id'])
    else:
        prev_cursor = None
        next_cursor = None

    results = {
        'perms': [],
        'items': items_list,
        'prev': prev_cursor,
        'cursor': cursor,
        'next': next_cursor,
    }

    return HttpResponseRest(request, results)
예제 #16
0
def get_panel_accession_list(request, panel_id):
    # check permission on this panel
    panel = get_object_or_404(AccessionPanel, id=int(panel_id))

    # check permission on this object
    from permission.utils import get_permissions_for
    perms = get_permissions_for(request.user, panel.content_type.app_label,
                                panel.content_type.model, panel.pk)
    if 'accession.get_accessionpanel' not in perms:
        raise PermissionDenied(_('Invalid permission to access to this panel'))

    results_per_page = int_arg(request.GET.get('more', 30))
    cursor = json.loads(request.GET.get('cursor', 'null'))
    limit = results_per_page
    sort_by = json.loads(request.GET.get('sort_by', '[]'))

    if not len(sort_by) or sort_by[-1] not in ('id', '+id', '-id'):
        order_by = sort_by + ['id']
    else:
        order_by = sort_by

    from main.cursor import CursorQuery
    cq = CursorQuery(Accession)

    if request.GET.get('search'):
        search = json.loads(request.GET['search'])
        cq.filter(search)

    if request.GET.get('filters'):
        filters = json.loads(request.GET['filters'])
        cq.filter(filters)

    cq.m2m_to_array_field(relationship=AccessionPanel.accessions,
                          selected_field='accessionpanel_id',
                          from_related_field='id',
                          to_related_field='accession_id',
                          alias='panels')

    cq.m2m_to_array_field(relationship=Accession.classifications_entries,
                          selected_field='classification_entry_id',
                          from_related_field='id',
                          to_related_field='accession_id',
                          alias='classifications')

    cq.set_synonym_model(AccessionSynonym)

    cq.prefetch_related(
        Prefetch("synonyms",
                 queryset=AccessionSynonym.objects.all().order_by(
                     'synonym_type', 'language')))

    cq.select_related('primary_classification_entry->name',
                      'primary_classification_entry->rank')

    cq.cursor(cursor, order_by)
    cq.inner_join(AccessionPanel, accessionpanel=int(panel_id))
    cq.order_by(order_by).limit(limit)

    accession_items = []

    synonym_types = dict(
        EntitySynonymType.objects.filter(
            target_model=ContentType.objects.get_for_model(
                Accession)).values_list('id', 'name'))

    for accession in cq:
        a = {
            'id': accession.pk,
            'name': accession.name,
            'code': accession.code,
            'primary_classification_entry':
            accession.primary_classification_entry_id,
            'layout': accession.layout_id,
            'descriptors': accession.descriptors,
            'synonyms': {},
            'primary_classification_entry_details': {
                'id': accession.primary_classification_entry_id,
                'name': accession.primary_classification_entry_name,
                'rank': accession.primary_classification_entry_rank_id,
            }
        }

        for synonym in accession.synonyms.all():
            synonym_type_name = synonym_types.get(synonym.synonym_type_id)
            a['synonyms'][synonym_type_name] = {
                'id': synonym.id,
                'name': synonym.name,
                'synonym_type': synonym.synonym_type_id,
                'language': synonym.language
            }

        accession_items.append(a)

    results = {
        'perms': [],
        'items': accession_items,
        'prev': cq.prev_cursor,
        'cursor': cursor,
        'next': cq.next_cursor,
    }

    return HttpResponseRest(request, results)