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)
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)
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)
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)
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)
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)
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, {})
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)
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)
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)
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)
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
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)
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)
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)
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)