Exemple #1
0
 def test_invalid_items(self):
     """`parse_pks` strip non-int values"""
     self.assertItemsEqual(parse_pks('1,2,a,b'), [1, 2])
     self.assertItemsEqual(parse_pks('a,b,1,2'), [1, 2])
     self.assertItemsEqual(parse_pks('1,a,b,2'), [1, 2])
     self.assertItemsEqual(parse_pks('a,1,b,2'), [1, 2])
     self.assertEqual(parse_pks('a,b'), [])
Exemple #2
0
 def test_items(self):
     """`parse_pks` will retrun in list all values that are integers.
     Extra spaces are allowed
     """
     self.assertItemsEqual(parse_pks('1'), [1])
     self.assertItemsEqual(parse_pks('1,2'), [1, 2])
     self.assertItemsEqual(parse_pks('1, 2, 3,'), [1, 2, 3])
     self.assertItemsEqual(parse_pks('-1, 1'), [-1, 1])
     self.assertItemsEqual(parse_pks('1, 1'), [1, 1])
Exemple #3
0
 def get_collections(self):
     """For given `request.POST.pks` get list of research project
     collections that will be assigned to classification project"""
     collection_pks = parse_pks(pks=self.request.POST.get('pks', ''))
     collections = ResearchProjectCollection.objects.get_accessible(
         user=self.request.user).filter(pk__in=collection_pks)
     return collections
Exemple #4
0
    def get(self, request, *args, **kwargs):
        """
        """

        project_pk = kwargs['project_pk']
        collection_pk = kwargs['collection_pk']
        collection = self.get_collection(project_pk=project_pk,
                                         collection_pk=collection_pk)
        deployments = request.GET.get('deployments', None)

        if deployments:
            params = {'resource__deployment__pk__in': parse_pks(deployments)}
        else:
            params = {}
        classification = collection.classifications.filter(
            **params).order_by('resource__date_recorded').first()

        if not classification:
            messages.error(
                request=self.request,
                message=('Selected collection contains no resources. '
                         'Nothing to classify.'))
            return redirect(
                reverse('media_classification:project_detail',
                        kwargs={'pk': project_pk}))
        url = reverse('media_classification:classify',
                      kwargs={'pk': classification.pk})
        if deployments:
            return redirect('{url}?deployments={deployments_pks}'.format(
                url=url, deployments_pks=deployments))
        else:
            return redirect(url)
Exemple #5
0
 def filter(self, qs, value):
     if value:
         pks = parse_pks(value)
         if pks:
             return qs.filter(
                 **{"{model_field}__in".format(model_field=self.name): pks})
     return qs
Exemple #6
0
 def get_collections(self):
     """Get list of collection pks's from `request.POST.pks` and
     return all collections that are accessible for user"""
     collection_pks = parse_pks(self.request.POST.get('pks', ''))
     collections = Collection.objects.get_accessible(
         user=self.request.user).filter(pk__in=collection_pks)
     return collections
Exemple #7
0
    def post(self, request, *args, **kwargs):
        """
        `request.POST` method is used to remove multiple resources
        from collection in a single request using AJAX.
        """
        user = request.user
        data = request.POST.get('pks', None)

        try:
            collection = Collection.objects.get(pk=kwargs.get('pk', None))
        except Collection.DoesNotExist:
            collection = None

        changed = []
        if data and collection and collection.can_update(user=user):
            values = parse_pks(pks=data)
            status = True
            msg = ''
            collection.resources.through.objects.filter(
                resource__in=values, collection=collection.pk).delete()
        else:
            status = False
            msg = 'Invlid request'

        context = {'status': status, 'msg': msg}
        return self.render_json_response(context)
Exemple #8
0
 def clean_locations_pks(self):
     locations_pks = self.cleaned_data.pop('locations_pks', None)
     if locations_pks:
         pks_list = parse_pks(locations_pks)
         locations = Location.objects.get_available(
             editable_only=True).filter(pk__in=pks_list)
         if locations:
             self.cleaned_data['locations'] = locations
Exemple #9
0
 def clean_records_pks(self):
     records_pks = self.cleaned_data.pop('records_pks', None)
     if records_pks:
         pks_list = parse_pks(records_pks)
         records = self.filter_editable()
         records = records.filter(pk__in=pks_list)
         if records:
             self.cleaned_data['records'] = records
Exemple #10
0
 def clean_resources_pks(self):
     resources_pks = self.cleaned_data.pop('resources_pks', None)
     if resources_pks:
         pks_list = parse_pks(resources_pks)
         resources = Resource.objects.get_accessible().filter(
             pk__in=pks_list)
         if resources:
             self.cleaned_data['resources'] = resources
Exemple #11
0
 def get_resources(self, collection, resource_pks):
     """For given collection and resource pk return
     :class:`apps.storage.model.Resource` objects but only those
     that are accessible for currently logged in user"""
     base_queryset = collection.collection.collection.resources.filter(
         pk__in=parse_pks(resource_pks))
     return Resource.objects.get_accessible(base_queryset=base_queryset,
                                            user=self.request.user,
                                            basic=True)
Exemple #12
0
 def clean_collections_pks(self):
     collections_pks = self.cleaned_data.pop('collections_pks', None)
     if collections_pks:
         pks_list = parse_pks(collections_pks)
         collections = ClassificationProjectCollection.objects.get_accessible(
             role_levels=[
                 ClassificationProjectRoleLevels.ADMIN,
             ]).filter(pk__in=pks_list)
         if collections:
             self.cleaned_data['project_collections'] = collections
Exemple #13
0
 def clean_selected_resources(self):
     error_msg = u"Classify multiple resources form has been tempered with."
     collection = self.initial.get('collection', None)
     if not collection:
         raise forms.ValidationError(error_msg)
     selected_resources = self.cleaned_data.get('selected_resources', None)
     resources = Resource.objects.filter(
         pk__in=parse_pks(pks=selected_resources),
         collection=collection.collection.collection)
     if not resources:
         raise forms.ValidationError(error_msg)
     return resources
Exemple #14
0
    def post(self, request, *args, **kwargs):
        """
        """
        user = self.request.user
        status = False
        msg = 'No resources to update or you have no permission \
        to update selected resources.'

        data = request.POST.copy()
        if 'classifications_pks' in data:

            classifications_pks = data['classifications_pks'] or ''
            del data['classifications_pks']
            classifications_pks = parse_pks(classifications_pks)
            classifications = Classification.objects.filter(
                Q(resource__owner=user) | Q(resource__managers=user)).filter(
                    pk__in=classifications_pks).select_related('resource')

            tag_keys = data.keys()

            if classifications:

                params = {
                    'data': {
                        'classifications': list(classifications),
                        'tag_keys': tag_keys
                    },
                    'user': user
                }
                if settings.CELERY_ENABLED:
                    task = celery_create_tags.delay(**params)
                    user_task = UserTask(user=user, task_id=task.task_id)
                    user_task.save()
                    msg = (
                        'You have successfully run a celery task. Tags for  '
                        'selected resources are being created now.')
                else:
                    msg = celery_create_tags(**params)
                status = True

        return self.render_json_response({
            'status': status,
            'msg': msg,
        })
Exemple #15
0
    def post(self, request, *args, **kwargs):
        """Delete multiple objects based on POST request. Object can be deleted
        only when request user has permission to do that.
        """
        user = request.user
        data = request.POST.get('pks', None)

        model = self.get_model()

        if data:
            values = parse_pks(pks=data)
            status = True
            msg = u''
            deleted = 0
            candidates = model.objects.filter(pk__in=values)
            candidates = self.filter_editable(candidates, user)

            total = len(candidates)

            if not total:
                status = False
                msg = (
                    u'No items to delete (most probably you have no permission '
                    u'to do that).')
            else:
                try:
                    self.bulk_delete(candidates)
                    msg = str(
                        total) + ' record(s) have been successfully deleted.'
                except ProtectedError:
                    status = False
                    msg = (
                        u'Some of selected items can not be deleted because '
                        u'they are referenced through a protected foreign key. '
                        u'Unselect them and re-run the action.')
        else:
            status = False
            msg = u'Invalid request'

        context = {'status': status, 'msg': msg}
        return self.render_json_response(context)
Exemple #16
0
    def post(self, request, *args, **kwargs):
        """
        `request.POST` method is used to alter multiple resources in single
        request using AJAX.

        List of resources pks is passed in `pks` key as list of integers
        separated by comma.

        Only owned resources can be updated.

        Response contains status of removal and list of resource pks that
        were changed.
        """
        user = request.user
        data = request.POST.get('pks', None)
        custom_prefix = request.POST.get('custom_prefix', None)
        inherit_prefix = request.POST.get('append', False) == 'true'

        changed = []
        status = False
        msg = ''
        if data:
            values = parse_pks(pks=data)
            candidates = Resource.objects.filter(pk__in=values).filter(
                (Q(owner=user) | Q(managers=user)))
            if candidates:
                if custom_prefix:
                    candidates.update(custom_prefix=custom_prefix)
                if inherit_prefix:
                    candidates = candidates.filter(
                        deployment__location__isnull=False)
                    if candidates:
                        candidates.update(inherit_prefix=inherit_prefix, )
                status = True
            else:
                msg = 'No resources to update'
        else:
            msg = 'Invalid request'

        context = {'status': status, 'msg': msg}
        return self.render_json_response(context)
Exemple #17
0
    def clean(self):
        """
        When collection and its resources are saved and the status 
        of this collection is set to "Public" or "OnDemand" check
        if this collection can be published or shared. This should 
        be only possible when a user has editing rights to all 
        resources that are part of this collection.
        """
        cleaned_data = super(CollectionForm, self).clean()
        status = cleaned_data.get('status')

        resources_pks = cleaned_data.pop('resources_pks', None)
        app = cleaned_data.pop('app', None)

        if resources_pks:
            pks_list = parse_pks(resources_pks)
            if app == 'media_classification':
                resources = Resource.objects.get_accessible().filter(
                    classifications__pk__in=pks_list)
            else:
                resources = Resource.objects.get_accessible().filter(
                    pk__in=pks_list)
            if resources:
                cleaned_data['resources'] = resources

        if status != 'Private':
            if self.instance.pk:
                resources = self.instance.resources.all()
            else:
                resources = cleaned_data.get('resources', None)
            if not resources:
                return cleaned_data
            user = get_current_user()
            n = resources.exclude(Q(owner=user) | Q(managers=user)).count()
            if n != 0:
                errors = mark_safe(
                    'You are not allowed to set the status of this collection '
                    'to <strong>{status}</strong> as you are not the owner of all resources '
                    'that are part of this collection.'.format(status=status))
                raise forms.ValidationError(errors)
        return cleaned_data
Exemple #18
0
 def clean_resources(self):
     """Convert resources from string of comma separated integers
     into list of integers"""
     resources = self.data.get('resources', None)
     return parse_pks(pks=resources)
Exemple #19
0
 def format_pks(self, pks):
     """Prepare list of pk from string"""
     return parse_pks(pks=pks)
Exemple #20
0
 def filter_deployments(self, qs, value):
     if value.strip() == "":
         return qs
     ids = parse_pks(pks=value)
     qs = qs.filter(deployments__pk__in=ids)
     return qs
Exemple #21
0
 def _format_value(self, value):
     return parse_pks(pks=value)
Exemple #22
0
 def test_invalid_separator(self):
     """`parse_pks` can handle invalid separator by returning empty list"""
     self.assertEqual(parse_pks('1:2'), [])
     self.assertEqual(parse_pks('1;2'), [])
Exemple #23
0
 def test_empty(self):
     """`parse_pks` can handle empty string by returning empty list"""
     self.assertEqual(parse_pks(''), [])
     self.assertEqual(parse_pks(u''), [])
Exemple #24
0
 def test_invalid_type(self):
     """`parse_pks` can handle invalid types by returning empty list"""
     self.assertEqual(parse_pks(None), [])
     self.assertEqual(parse_pks([]), [])
     self.assertEqual(parse_pks(()), [])
     self.assertEqual(parse_pks(b'test'), [])
    def post(self, request, *args, **kwargs):
        user = request.user
        timestamp = now()
        data = request.POST.get('pks', None)

        if data:
            values = parse_pks(pks=data)
            user_classifications = UserClassification.objects.filter(
                classification__project=self.project,
                pk__in=values).select_related(
                    'classification',
                    'owner').prefetch_related('dynamic_attrs')
            total = len(user_classifications)
            if not total:
                status = False
                msg = 'No items to delete (most probably you have no permission to do that).'
                context = {'status': status, 'msg': msg}
                return self.render_json_response(context)

            users = [k.owner for k in user_classifications]
            if len(set(users)) != 1:
                status = False
                msg = (
                    'You can run this action only for a set of classifications '
                    'that all belong to a one user.')
                context = {'status': status, 'msg': msg}
                return self.render_json_response(context)

            # bulk update classification objects
            classifications_to_update = []
            dynamic_attrs_objects = []

            for uc in user_classifications:
                classification = uc.classification
                classification.status = True
                classification.approved_by_id = user.pk
                classification.approved_at = str(timestamp)
                classification.approved_source_id = uc.pk
                classification.static_attrs = uc.static_attrs
                classifications_to_update.append(classification)

                for dynamic_row in uc.dynamic_attrs.all():
                    dynamic_attrs_objects.append(
                        ClassificationDynamicAttrs(
                            classification_id=classification.pk,
                            attrs=dynamic_row.attrs))

            bulk_update(classifications_to_update,
                        update_fields=[
                            'status', 'approved_by_id', 'approved_at',
                            'approved_source_id', 'static_attrs'
                        ])

            # bulk delete ClassificationDynamicAttrs objects
            ClassificationDynamicAttrs.objects.filter(
                classification__in=classifications_to_update).delete()

            # bulk create ClassificationDynamicAttrs objects
            ClassificationDynamicAttrs.objects.bulk_create(
                dynamic_attrs_objects)

        else:
            status = False
            msg = 'Invalid request'

        status = True
        msg = ('You have successfully approved <strong>{n}</strong> user '
               'classifications.'.format(n=total))
        context = {'status': status, 'msg': msg}
        return self.render_json_response(context)
Exemple #26
0
    def post(self, request, *args, **kwargs):
        """
        `request.POST` method is used to append multiple resources
        to collection in single request.

        List of resources pks is passed in `pks` key as list of integers
        separated by comma.

        Before append, all resources pks are validated if user can view
        them and only those, which user has enough permissions for, are
        added to collection.

        Response contains status of update and list of resource pks that
        were added.

        After that, user is redirected to collection details.
        """
        user = request.user
        collection_pk = request.POST.get('collection', None)
        resources_pk = request.POST.get('resources', None)
        app = request.POST.get('app', None)
        resources_url = reverse('storage:resource_list')
        resources = None

        if resources_pk:
            resources_pk = parse_pks(pks=resources_pk)
            if app == 'media_classification':
                base_queryset = Resource.objects.filter(
                    classifications__pk__in=resources_pk)
            else:
                base_queryset = Resource.objects.filter(pk__in=resources_pk)
            resources = Resource.objects.get_accessible(
                base_queryset=base_queryset)

        if not resources:
            messages.error(
                request,
                'You have no permissions to add any of selected resources.')
            return redirect(resources_url)

        collection = get_object_or_404(Collection, pk=collection_pk)
        collection_url = reverse('storage:collection_detail',
                                 kwargs={'pk': collection.pk})

        if not collection.can_update(user=user):
            messages.error(
                request, 'You have no permissions to modify this collection.')
            return redirect(resources_url)

        if not collection.status == 'Private':
            n = resources.exclude(Q(owner=user) | Q(managers=user)).count()
            if n != 0:
                messages.error(
                    request,
                    'You have no permission to add some of selected resources '
                    'to this "{ctype}" collection'.format(
                        ctype=collection.status.lower()))
                return redirect(resources_url)

        new_resources = resources.exclude(
            pk__in=collection.resources.values_list('pk', flat=True))

        if not new_resources:
            messages.warning(
                request,
                'The selected resources already are in this collection.')
            return redirect(collection_url)

        messages.success(
            request, 'You have successfully added <strong>{len}</strong> new '
            'resources to this collection.'.format(len=new_resources.count()))

        collection.resources.add(*new_resources)
        return redirect(collection_url)