Ejemplo n.º 1
0
    def post(self, request, collection):
        """Create a new collection

        View to create a new collection and an associated bosskey for that collection
        Args:
            request: DRF Request object
            collection : Collection name
        Returns:
            Collection

        """
        col_data = request.data.copy()
        col_data['name'] = collection

        # Save the object
        serializer = CollectionSerializer(data=col_data)
        if serializer.is_valid():
            serializer.save(creator=self.request.user)
            collection_obj = Collection.objects.get(name=col_data['name'])

            # Assign permissions to the users primary group and admin group
            BossPermissionManager.add_permissions_primary_group(self.request.user, collection_obj)
            BossPermissionManager.add_permissions_admin_group(collection_obj)

            lookup_key = str(collection_obj.pk)
            boss_key = collection_obj.name
            LookUpKey.add_lookup(lookup_key, boss_key, collection_obj.name)

            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT)
Ejemplo n.º 2
0
    def post(self, request, coordframe):
        """Create a new coordinate frame

        View to create a new coordinate frame
        Args:
            request: DRF Request object
            coordframe : Coordinate frame name
        Returns:
            CoordinateFrame

        """
        coordframe_data = request.data.copy()
        coordframe_data['name'] = coordframe

        serializer = CoordinateFrameSerializer(data=coordframe_data)
        if serializer.is_valid():
            serializer.save(creator=self.request.user)
            coordframe_obj = CoordinateFrame.objects.get(name=coordframe_data['name'])

            # Assign permissions to the users primary group and admin group
            BossPermissionManager.add_permissions_primary_group(self.request.user, coordframe_obj)
            BossPermissionManager.add_permissions_admin_group(coordframe_obj)

            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT)
Ejemplo n.º 3
0
    def patch(self, request):
        """ Patch permissions for a resource

        Remove specific permissions for a existing group and resource object
        Args:
            request: Django rest framework request
        Returns:
            Http status code

        """
        if 'permissions' not in request.data:
            return BossHTTPError("Permission are not included in the request", ErrorCodes. UNABLE_TO_VALIDATE)
        else:
            perm_list = dict(request.data)['permissions']

        if 'group' not in request.data:
            return BossHTTPError("Group are not included in the request", ErrorCodes. UNABLE_TO_VALIDATE)

        if 'collection' not in request.data:
            return BossHTTPError("Invalid resource or missing resource name in request", ErrorCodes. UNABLE_TO_VALIDATE)

        group_name = request.data.get('group', None)
        collection = request.data.get('collection', None)
        experiment = request.data.get('experiment', None)
        channel = request.data.get('channel', None)

        try:
            # public group can only have read permission
            if group_name == 'public' and (len(perm_list) != 1 or perm_list[0] != 'read'):
                return BossHTTPError("The public group can only have read permissions",
                                     ErrorCodes.INVALID_POST_ARGUMENT)
            # If the user is not a member or maintainer of the group, they cannot patch permissions
            if not check_is_member_or_maintainer(request.user, group_name):
                return BossHTTPError('The user {} is not a member or maintainer of the group {} '.
                                     format(request.user.username, group_name), ErrorCodes.MISSING_PERMISSION)

            resource_object = self.get_object(collection, experiment, channel)
            if resource_object is None:
                return BossHTTPError("Unable to validate the resource", ErrorCodes.UNABLE_TO_VALIDATE)

            resource = resource_object[0]
            # remove all existing permission for the group
            if request.user.has_perm("remove_group", resource) and request.user.has_perm("assign_group", resource):
                BossPermissionManager.delete_all_permissions_group(group_name, resource)
                BossPermissionManager.add_permissions_group(group_name, resource, perm_list)
                return Response(status=status.HTTP_200_OK)
            else:
                return BossPermissionError('remove group', resource.name)

        except Group.DoesNotExist:
            return BossGroupNotFoundError(group_name)
        except Permission.DoesNotExist:
            return BossHTTPError("Invalid permissions in post".format(request.data['permissions']),
                                 ErrorCodes.UNRECOGNIZED_PERMISSION)
        except BossError as err:
            return err.to_http()
Ejemplo n.º 4
0
    def post(self, request):
        """ Add permissions to a resource

        Add new permissions for a existing group and resource object

        Args:
            request: Django rest framework request

        Returns:
            Http status code

        """
        if 'permissions' not in request.data:
            return BossHTTPError("Permission are not included in the request", ErrorCodes.INVALID_URL)
        else:
            perm_list = dict(request.data)['permissions']

        if 'group' not in request.data:
            return BossHTTPError("Group are not included in the request", ErrorCodes.INVALID_URL)

        if 'collection' not in request.data:
            return BossHTTPError("Invalid resource or missing resource name in request", ErrorCodes.INVALID_URL)

        group_name = request.data.get('group', None)
        collection = request.data.get('collection', None)
        experiment = request.data.get('experiment', None)
        channel = request.data.get('channel', None)

        try:
            # public group can only have read permission
            if group_name == 'public' and not (set(perm_list).issubset({'read', 'read_volumetric_data'})):
                return BossHTTPError("The public group can only have read permissions",
                                     ErrorCodes.INVALID_POST_ARGUMENT)

            # If the user is not a member or maintainer of the group, they cannot assign permissions
            if not check_is_member_or_maintainer(request.user, group_name):
                return BossHTTPError('The user {} is not a member or maintainer of the group {} '.
                                     format(request.user.username, group_name), ErrorCodes.MISSING_PERMISSION)

            resource_object = self.get_object(collection, experiment, channel)
            if resource_object is None:
                return BossHTTPError("Unable to validate the resource", ErrorCodes.UNABLE_TO_VALIDATE)
            resource = resource_object[0]
            if request.user.has_perm("assign_group", resource):
                BossPermissionManager.add_permissions_group(group_name, resource, perm_list)
                return Response(status=status.HTTP_201_CREATED)
            else:
                return BossPermissionError('assign group', collection)

        except Group.DoesNotExist:
            return BossGroupNotFoundError(group_name)
        except Permission.DoesNotExist:
            return BossHTTPError("Invalid permissions in post".format(request.data['permissions']),
                                 ErrorCodes.UNRECOGNIZED_PERMISSION)
        except BossError as err:
            return err.to_http()
Ejemplo n.º 5
0
    def delete(self, request):
        """ Delete permissions for a resource object

       Remove specific permissions for a existing group and resource object

       Args:
            request: Django rest framework request
       Returns:
            Http status code

       """
        if 'group' not in request.query_params:
            return BossHTTPError("Group are not included in the request",
                                 ErrorCodes.INVALID_URL)

        if 'collection' not in request.query_params:
            return BossHTTPError(
                "Invalid resource or missing resource name in request",
                ErrorCodes.INVALID_URL)

        group_name = request.query_params.get('group', None)
        collection = request.query_params.get('collection', None)
        experiment = request.query_params.get('experiment', None)
        channel = request.query_params.get('channel', None)
        try:
            if not check_is_member_or_maintainer(request.user, group_name):
                return BossHTTPError(
                    'The user {} is not a member or maintainer of the group {} '
                    .format(request.user.username,
                            group_name), ErrorCodes.MISSING_PERMISSION)

            resource_object = self.get_object(collection, experiment, channel)
            if resource_object is None:
                return BossHTTPError("Unable to validate the resource",
                                     ErrorCodes.UNABLE_TO_VALIDATE)

            if request.user.has_perm("remove_group", resource_object[0]):
                BossPermissionManager.delete_all_permissions_group(
                    group_name, resource_object[0])
                return Response(status=status.HTTP_204_NO_CONTENT)
            else:
                return BossPermissionError('remove group',
                                           resource_object[0].name)

        except Group.DoesNotExist:
            return BossGroupNotFoundError(group_name)
        except Permission.DoesNotExist:
            return BossHTTPError(
                "Invalid permissions in post".format(
                    request.data['permissions']),
                ErrorCodes.UNRECOGNIZED_PERMISSION)
        except Exception as e:
            return BossHTTPError("{}".format(e),
                                 ErrorCodes.UNHANDLED_EXCEPTION)
        except BossError as err:
            return err.to_http()
Ejemplo n.º 6
0
    def post(self, request, collection, experiment):
        """Create a new experiment

        View to create a new experiment and an associated bosskey for that experiment
        Args:
            request: DRF Request object
            collection : Collection name
            experiment : Experiment name
        Returns:
            Experiment

        """
        experiment_data = request.data.copy()
        experiment_data['name'] = experiment
        try:
            # Get the collection information
            collection_obj = Collection.objects.get(name=collection)

            if request.user.has_perm("add", collection_obj):
                experiment_data['collection'] = collection_obj.pk

                # Update the coordinate frame
                if 'coord_frame' not in experiment_data:
                    return BossHTTPError("This request requires a valid coordinate frame",
                                         ErrorCodes.INVALID_POST_ARGUMENT)

                coord_frame_obj = CoordinateFrame.objects.get(name=experiment_data['coord_frame'])
                experiment_data['coord_frame'] = coord_frame_obj.pk

                serializer = ExperimentSerializer(data=experiment_data)
                if serializer.is_valid():
                    serializer.save(creator=self.request.user)
                    experiment_obj = Experiment.objects.get(name=experiment_data['name'], collection=collection_obj)

                    # Assign permissions to the users primary group and admin group
                    BossPermissionManager.add_permissions_primary_group(self.request.user, experiment_obj)
                    BossPermissionManager.add_permissions_admin_group(experiment_obj)

                    lookup_key = str(collection_obj.pk) + '&' + str(experiment_obj.pk)
                    boss_key = collection_obj.name + '&' + experiment_obj.name
                    LookUpKey.add_lookup(lookup_key, boss_key, collection_obj.name, experiment_obj.name)

                    serializer = ExperimentReadSerializer(experiment_obj)
                    return Response(serializer.data, status=status.HTTP_201_CREATED)
                else:
                    return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT)
            else:
                return BossPermissionError('add', collection)
        except Collection.DoesNotExist:
            return BossResourceNotFoundError(collection)
        except CoordinateFrame.DoesNotExist:
            return BossResourceNotFoundError(experiment_data['coord_frame'])
        except ValueError:
            return BossHTTPError("Value Error.Collection id {} in post data needs to be an integer"
                                 .format(experiment_data['collection']), ErrorCodes.TYPE_ERROR)
Ejemplo n.º 7
0
    def post(self,
             request,
             group_name,
             collection,
             experiment=None,
             channel_layer=None):
        """ Add permissions to a resource

        Add new permissions for a existing group and resource object

        Args:
            request: Django rest framework request
            group_name: Group name of an existing group
            collection: Collection name from the request
            experiment: Experiment name from the request
            channel_layer: Channel or layer name from the request

        Returns:
            Http status code

        """
        if 'permissions' not in request.data:
            return BossHTTPError("Permission are not included in the request",
                                 ErrorCodes.INCOMPLETE_REQUEST)
        else:
            perm_list = dict(request.data)['permissions']

        try:
            obj = self.get_object(collection, experiment, channel_layer)

            if request.user.has_perm("assign_group", obj):
                BossPermissionManager.add_permissions_group(
                    group_name, obj, perm_list)
                return Response(status=status.HTTP_201_CREATED)
            else:
                return BossPermissionError('assign group', collection)

        except Group.DoesNotExist:
            return BossGroupNotFoundError(group_name)
        except Permission.DoesNotExist:
            return BossHTTPError(
                "Invalid permissions in post".format(
                    request.data['permissions']),
                ErrorCodes.UNRECOGNIZED_PERMISSION)
        except BossError as err:
            return err.to_http()
Ejemplo n.º 8
0
    def delete(self, request):
        """ Delete permissions for a resource object

       Remove specific permissions for a existing group and resource object

       Args:
            request: Django rest framework request
       Returns:
            Http status code

       """
        if 'group' not in request.query_params:
            return BossHTTPError("Group are not included in the request", ErrorCodes.INVALID_URL)

        if 'collection' not in request.query_params:
            return BossHTTPError("Invalid resource or missing resource name in request", ErrorCodes.INVALID_URL)

        group_name = request.query_params.get('group', None)
        collection = request.query_params.get('collection', None)
        experiment = request.query_params.get('experiment', None)
        channel = request.query_params.get('channel', None)
        try:
            if not check_is_member_or_maintainer(request.user, group_name):
                return BossHTTPError('The user {} is not a member or maintainer of the group {} '.
                                     format(request.user.username, group_name), ErrorCodes.MISSING_PERMISSION)

            resource_object = self.get_object(collection, experiment, channel)
            if resource_object is None:
                return BossHTTPError("Unable to validate the resource", ErrorCodes.UNABLE_TO_VALIDATE)

            if request.user.has_perm("remove_group", resource_object[0]):
                BossPermissionManager.delete_all_permissions_group(group_name, resource_object[0])
                return Response(status=status.HTTP_204_NO_CONTENT)
            else:
                return BossPermissionError('remove group', resource_object[0].name)

        except Group.DoesNotExist:
            return BossGroupNotFoundError(group_name)
        except Permission.DoesNotExist:
            return BossHTTPError("Invalid permissions in post".format(request.data['permissions']),
                                 ErrorCodes.UNRECOGNIZED_PERMISSION)
        except Exception as e:
            return BossHTTPError("{}".format(e), ErrorCodes.UNHANDLED_EXCEPTION)
        except BossError as err:
            return err.to_http()
Ejemplo n.º 9
0
    def get(self,
            request,
            group_name,
            collection,
            experiment=None,
            channel_layer=None):
        """Return a list of permissions

        Get the list of the permissions for a group on a resource. These determine the access for the users
        in the group on the resource

        Args:
           request: Django Rest framework request
           group_name: Group name of an existing group
           collection: Collection name from the request
           experiment: Experiment name from the request
           channel_layer: Channel or Layer name from the request

       Returns:
           List of permissions

        """
        try:

            obj = self.get_object(collection, experiment, channel_layer)

            perm = BossPermissionManager.get_permissions_group(group_name, obj)
            data = {'group': group_name, 'permissions': perm}
            return Response(data,
                            status=status.HTTP_201_CREATED,
                            content_type='application/json')

        except Group.DoesNotExist:
            return BossGroupNotFoundError(group_name)
        except Permission.DoesNotExist:
            return BossHTTPError(
                "Invalid permissions in post".format(
                    request.data['permissions']),
                ErrorCodes.UNRECOGNIZED_PERMISSION)
        except BossError as err:
            return err.to_http()
Ejemplo n.º 10
0
    def post(self, request, collection_name, experiment_name, channel_name):
        action = request.GET.get('action')  # URL parameter

        if action == 'meta':
            form = MetaForm(request.POST)
            if form.is_valid():
                key = form.cleaned_data['key']
                value = form.cleaned_data['value']

                err = api.add_meta(request, key, value, collection_name,
                                   experiment_name, channel_name)
                if err:
                    form.add_error(None, err)
                else:
                    return redirect('mgmt:channel', collection_name,
                                    experiment_name, channel_name)
            return self.get(request,
                            collection_name,
                            experiment_name,
                            channel_name,
                            meta_form=form)
        elif action == 'perms':
            form = ResourcePermissionsForm(request.POST)
            if form.is_valid():
                err = utils.set_perms(request, form, collection_name,
                                      experiment_name, channel_name)
                if err:
                    form.add_error(None, err)
                else:
                    return redirect('mgmt:channel', collection_name,
                                    experiment_name, channel_name)
            return self.get(request,
                            collection_name,
                            experiment_name,
                            channel_name,
                            perms_form=form)
        elif action == 'update':
            form = ChannelForm(request.POST)

            # DEV NOTE: Some fields only update-able if request originates from admin
            is_admin = BossPermissionManager.is_in_group(
                request.user, ADMIN_GRP)
            data = form.data.copy()
            data['is_admin'] = is_admin
            form.data = data

            if form.is_valid():
                data = form.cleaned_update_data

                # DMK - Boss request throws a BossError if the related channels don't exist
                try:
                    err = api.up_channel(request, collection_name,
                                         experiment_name, channel_name, data)

                    if err:
                        form.add_error(None, err)
                    else:
                        return redirect('mgmt:channel', collection_name,
                                        experiment_name, data['name'])

                except BossError as err:
                    form.add_error(None, err.message)

            return self.get(request,
                            collection_name,
                            experiment_name,
                            channel_name,
                            chan_form=form)
        else:
            return HttpResponse(status=400, reason="Unknown post action")
Ejemplo n.º 11
0
    def get(self,
            request,
            collection_name,
            experiment_name,
            channel_name,
            chan_form=None,
            meta_form=None,
            perms_form=None):
        page_error = None

        remove = request.GET.get('rem_perms')
        if remove is not None:
            err = api.del_perms(request,
                                collection_name,
                                experiment_name,
                                channel_name,
                                group=remove)
            if err:
                page_error = err
            else:
                return redirect('mgmt:channel', collection_name,
                                experiment_name, channel_name)

        channel, err = api.get_channel(request, collection_name,
                                       experiment_name, channel_name)
        if err:
            return err

        if not chan_form:
            is_admin = BossPermissionManager.is_in_group(
                request.user, ADMIN_GRP)
            channel['is_admin'] = is_admin
            chan_form = ChannelForm(channel).is_update()
            chan_error = ""
        else:
            chan_form.is_update()
            chan_error = "error"

        metas, err = api.get_meta_keys(request, collection_name,
                                       experiment_name, channel_name)
        if err:
            return err

        perms, err = utils.get_perms(request, collection_name, experiment_name,
                                     channel_name)
        if err:
            return err

        args = {
            'user_roles': get_roles(request),
            'page_error': page_error,
            'collection_name': collection_name,
            'experiment_name': experiment_name,
            'channel_name': channel_name,
            'channel': channel,
            'metas': metas,
            'perms': perms,
            'chan_form': chan_form,
            'chan_error': chan_error,
            'meta_form': meta_form if meta_form else MetaForm(),
            'meta_error': "error" if meta_form else "",
            'perms_form':
            perms_form if perms_form else ResourcePermissionsForm(),
            'perms_error': "error" if perms_form else "",
        }
        return HttpResponse(
            render_to_string('channel.html', args, request=request))
Ejemplo n.º 12
0
    def get(self,
            request,
            collection_name,
            experiment_name,
            exp_form=None,
            chan_form=None,
            meta_form=None,
            perms_form=None):
        page_error = None

        remove = request.GET.get('rem_perms')
        if remove is not None:
            err = api.del_perms(request,
                                collection_name,
                                experiment_name,
                                group=remove)
            if err:
                page_error = err
            else:
                return redirect('mgmt:experiment', collection_name,
                                experiment_name)

        experiment, err = api.get_experiment(request, collection_name,
                                             experiment_name)
        if err:
            return err

        if not exp_form:
            exp_form = ExperimentForm(experiment).is_update()
            exp_error = ""
        else:
            exp_form.is_update()
            exp_error = "error"

        metas, err = api.get_meta_keys(request, collection_name,
                                       experiment_name)
        if err:
            return err

        perms, err = utils.get_perms(request, collection_name, experiment_name)
        if err:
            return err

        args = {
            'user_roles': get_roles(request),
            'page_error': page_error,
            'collection_name': collection_name,
            'experiment_name': experiment_name,
            'experiment': experiment,
            'metas': metas,
            'perms': perms,
            'exp_form': exp_form,
            'exp_error': exp_error,
            'chan_form': chan_form if chan_form else None,
            'chan_error': "error" if chan_form else "",
            'meta_form': meta_form if meta_form else MetaForm(),
            'meta_error': "error" if meta_form else "",
            'perms_form':
            perms_form if perms_form else ResourcePermissionsForm(),
            'perms_error': "error" if perms_form else "",
        }
        if args['chan_form'] is None:
            is_admin = BossPermissionManager.is_in_group(
                request.user, ADMIN_GRP)
            new_chan_form = ChannelForm(initial={
                "base_resolution": 0,
                "default_time_sample": 0
            })
            if not is_admin:
                new_chan_form.disable_non_admin_fields()
            args['chan_form'] = new_chan_form

        return HttpResponse(
            render_to_string('experiment.html', args, request=request))
Ejemplo n.º 13
0
    def post(self, request, collection, experiment, channel):
        """
        Post a new Channel
        Args:
            request: DRF Request object
            collection: Collection name
            experiment: Experiment name
            channel: Channel name

        Returns :
            Channel
        """

        channel_data = request.data.copy()
        channel_data['name'] = channel

        try:
            # Get the collection and experiment
            collection_obj = Collection.objects.get(name=collection)
            experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj)

            # Check for add permissions
            if request.user.has_perm("add", experiment_obj):
                channel_data['experiment'] = experiment_obj.pk

                # The source and related channels are names and need to be removed from the dict before serialization
                source_channels = channel_data.pop('sources', [])
                related_channels = channel_data.pop('related', [])

                # Source channels have to be included for new annotation channels
                if 'type' in channel_data and channel_data['type'] == 'annotation' and len(source_channels) == 0:
                    return BossHTTPError("Annotation channels require the source channel to be set. "
                                         "Specify a valid source channel in the post", ErrorCodes.INVALID_POST_ARGUMENT)

                # Validate the source and related channels if they are incuded
                channels = self.validate_source_related_channels(experiment_obj, source_channels, related_channels)
                source_channels_objs = channels[0]
                related_channels_objs = channels[1]

                # Validate and create the channel
                serializer = ChannelSerializer(data=channel_data)
                if serializer.is_valid():
                    serializer.save(creator=self.request.user)
                    channel_obj = Channel.objects.get(name=channel_data['name'], experiment=experiment_obj)

                    # Save source and related channels if they are valid
                    channel_obj = self.add_source_related_channels(channel_obj, experiment_obj, source_channels_objs,
                                                                   related_channels_objs)

                    # Assign permissions to the users primary group and admin group
                    BossPermissionManager.add_permissions_primary_group(self.request.user, channel_obj)
                    BossPermissionManager.add_permissions_admin_group(channel_obj)

                    # Add Lookup key
                    lookup_key = str(collection_obj.pk) + '&' + str(experiment_obj.pk) + '&' + str(channel_obj.pk)
                    boss_key = collection_obj.name + '&' + experiment_obj.name + '&' + channel_obj.name
                    LookUpKey.add_lookup(lookup_key, boss_key, collection_obj.name, experiment_obj.name,
                                         channel_obj.name)

                    serializer = ChannelReadSerializer(channel_obj)
                    return Response(serializer.data, status=status.HTTP_201_CREATED)
                else:
                    return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT)
            else:
                return BossPermissionError('add', experiment)
        except Collection.DoesNotExist:
            return BossResourceNotFoundError(collection)
        except Experiment.DoesNotExist:
            return BossResourceNotFoundError(experiment)
        except Channel.DoesNotExist:
            return BossResourceNotFoundError(channel)
        except BossError as err:
            return err.to_http()
        except ValueError:
            return BossHTTPError("Value Error in post data", ErrorCodes.TYPE_ERROR)
Ejemplo n.º 14
0
    def put(self, request, collection, experiment, channel):
        """
        Update new Channel
        Args:
            request: DRF Request object
            collection: Collection name
            experiment: Experiment name
            channel: Channel name

        Returns :
            Channel
        """
        if 'name' in request.data:
            channel_name = request.data['name']
        else:
            channel_name = channel
        try:
            # Check if the object exists
            collection_obj = Collection.objects.get(name=collection)
            experiment_obj = Experiment.objects.get(name=experiment,
                                                    collection=collection_obj)
            channel_obj = Channel.objects.get(name=channel,
                                              experiment=experiment_obj)

            if request.user.has_perm("update", channel_obj):

                data = copy.deepcopy(request.data)
                is_admin = BossPermissionManager.is_in_group(
                    request.user, ADMIN_GRP)

                if 'storage_type' in data and not is_admin:
                    return BossHTTPError(
                        'Only admins can change storage_type after creation',
                        ErrorCodes.MISSING_PERMISSION)

                if 'bucket' in data and data['bucket'] and not is_admin:
                    return BossHTTPError('Only admins can set bucket name',
                                         ErrorCodes.MISSING_PERMISSION)

                if 'cv_path' in data and data['cv_path'] and not is_admin:
                    return BossHTTPError('Only admins can set cv_path',
                                         ErrorCodes.MISSING_PERMISSION)

                # The source and related channels are names and need to be removed from the dict before serialization
                source_channels = data.pop('sources', [])
                related_channels = data.pop('related', [])

                # Validate the source and related channels if they are incuded
                channels = self.validate_source_related_channels(
                    experiment_obj, source_channels, related_channels)
                source_channels_objs = channels[0]
                related_channels_objs = channels[1]

                serializer = ChannelUpdateSerializer(channel_obj,
                                                     data=data,
                                                     partial=True)
                if serializer.is_valid():
                    serializer.save()

                    channel_obj = Channel.objects.get(
                        name=channel_name, experiment=experiment_obj)
                    # Save source and related channels if they are valid
                    channel_obj = self.update_source_related_channels(
                        channel_obj, experiment_obj, source_channels_objs,
                        related_channels_objs)

                    # update the lookup key if you update the name
                    if 'name' in data and data['name'] != channel:
                        lookup_key = str(collection_obj.pk) + '&' + str(experiment_obj.pk) + '&' \
                                     + str(channel_obj.pk)
                        boss_key = collection_obj.name + '&' + experiment_obj.name + '&' + data[
                            'name']
                        LookUpKey.update_lookup(lookup_key, boss_key,
                                                collection_obj.name,
                                                experiment_obj.name,
                                                data['name'])

                    # return the object back to the user
                    channel = serializer.data['name']
                    channel_obj = Channel.objects.get(
                        name=channel, experiment=experiment_obj)
                    serializer = ChannelReadSerializer(channel_obj)
                    return Response(serializer.data)
                else:
                    return BossHTTPError("{}".format(serializer.errors),
                                         ErrorCodes.INVALID_POST_ARGUMENT)
            else:
                return BossPermissionError('update', channel)

        except Collection.DoesNotExist:
            return BossResourceNotFoundError(collection)
        except Experiment.DoesNotExist:
            return BossResourceNotFoundError(experiment)
        except Channel.DoesNotExist:
            return BossResourceNotFoundError(channel)
Ejemplo n.º 15
0
    def post(self, request, collection, experiment, channel):
        """
        Post a new Channel
        Args:
            request: DRF Request object
            collection: Collection name
            experiment: Experiment name
            channel: Channel name

        Returns :
            Channel
        """

        channel_data = request.data.copy()
        channel_data['name'] = channel

        try:
            is_admin = BossPermissionManager.is_in_group(
                request.user, ADMIN_GRP)
            if 'bucket' in channel_data and channel_data[
                    'bucket'] and not is_admin:
                return BossHTTPError('Only admins can set bucket name',
                                     ErrorCodes.MISSING_PERMISSION)

            if 'cv_path' in channel_data and channel_data[
                    'cv_path'] and not is_admin:
                return BossHTTPError('Only admins can set cv_path',
                                     ErrorCodes.MISSING_PERMISSION)

            # Get the collection and experiment
            collection_obj = Collection.objects.get(name=collection)
            experiment_obj = Experiment.objects.get(name=experiment,
                                                    collection=collection_obj)

            # Check for add permissions
            if request.user.has_perm("add", experiment_obj):
                channel_data['experiment'] = experiment_obj.pk

                use_cloudvol = channel_data.get(
                    'storage_type', None) == Channel.StorageType.CLOUD_VOLUME
                cv_path = channel_data.get('cv_path', None)
                if use_cloudvol and (cv_path is None or cv_path == ''):
                    channel_data[
                        'cv_path'] = f'/{collection}/{experiment}/{channel}'

                if use_cloudvol:
                    # DX NOTE: For now we assume that cloudvolume channels are downsampled. This means
                    # that the num_hierarchy_levels in the experiment should be limited to the available
                    # mip levels in the cloudvolume layer.
                    channel_data['downsample_status'] = 'DOWNSAMPLED'

                # The source and related channels are names and need to be removed from the dict before serialization
                source_channels = channel_data.pop('sources', [])
                related_channels = channel_data.pop('related', [])

                # TODO: Removed source channel requirement for annotation channels. Future update should allow source channel from
                # different collections.

                # Source channels have to be included for new annotation channels
                # if 'type' in channel_data and channel_data['type'] == 'annotation' and len(source_channels) == 0:
                #     return BossHTTPError("Annotation channels require the source channel to be set. "
                #                          "Specify a valid source channel in the post", ErrorCodes.INVALID_POST_ARGUMENT)

                # Validate the source and related channels if they are incuded
                channels = self.validate_source_related_channels(
                    experiment_obj, source_channels, related_channels)
                source_channels_objs = channels[0]
                related_channels_objs = channels[1]

                # Validate and create the channel
                serializer = ChannelSerializer(data=channel_data)
                if serializer.is_valid():
                    serializer.save(creator=self.request.user)
                    channel_obj = Channel.objects.get(
                        name=channel_data['name'], experiment=experiment_obj)

                    # Save source and related channels if they are valid
                    channel_obj = self.add_source_related_channels(
                        channel_obj, experiment_obj, source_channels_objs,
                        related_channels_objs)

                    # Assign permissions to the users primary group and admin group
                    BossPermissionManager.add_permissions_primary_group(
                        self.request.user, channel_obj)
                    BossPermissionManager.add_permissions_admin_group(
                        channel_obj)

                    # Add Lookup key
                    lookup_key = str(collection_obj.pk) + '&' + str(
                        experiment_obj.pk) + '&' + str(channel_obj.pk)
                    boss_key = collection_obj.name + '&' + experiment_obj.name + '&' + channel_obj.name
                    LookUpKey.add_lookup(lookup_key, boss_key,
                                         collection_obj.name,
                                         experiment_obj.name, channel_obj.name)

                    serializer = ChannelReadSerializer(channel_obj)
                    return Response(serializer.data,
                                    status=status.HTTP_201_CREATED)
                else:
                    return BossHTTPError("{}".format(serializer.errors),
                                         ErrorCodes.INVALID_POST_ARGUMENT)
            else:
                return BossPermissionError('add', experiment)
        except Collection.DoesNotExist:
            return BossResourceNotFoundError(collection)
        except Experiment.DoesNotExist:
            return BossResourceNotFoundError(experiment)
        except Channel.DoesNotExist:
            return BossResourceNotFoundError(channel)
        except BossError as err:
            return err.to_http()
        except ValueError:
            return BossHTTPError("Value Error in post data",
                                 ErrorCodes.TYPE_ERROR)
Ejemplo n.º 16
0
    def post(self, request, collection, experiment, channel_layer):
        """
        Post a new Channel
        Args:
            request: DRF Request object
            collection: Collection name
            experiment: Experiment name
            channel_layer: Channel or Layer name

        Returns :
            ChannelLayer
        """

        channel_layer_data = request.data.copy()
        channel_layer_data['name'] = channel_layer

        try:
            if 'channels' in channel_layer_data:
                channels = dict(channel_layer_data)['channels']
            else:
                channels = []
            collection_obj = Collection.objects.get(name=collection)
            experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj)
            # Check for add permissions
            if request.user.has_perm("add", experiment_obj):
                channel_layer_data['experiment'] = experiment_obj.pk
                channel_layer_data['is_channel'] = self.get_bool(channel_layer_data['is_channel'])

                # layers require at least 1 channel
                if (channel_layer_data['is_channel'] is False) and (len(channels) == 0):
                    return BossHTTPError("Invalid Request.Please specify a valid channel for the layer",
                                         ErrorCodes.INVALID_POST_ARGUMENT)

                serializer = ChannelLayerSerializer(data=channel_layer_data)
                if serializer.is_valid():
                    serializer.save(creator=self.request.user)
                    channel_layer_obj = ChannelLayer.objects.get(name=channel_layer_data['name'],
                                                                 experiment=experiment_obj)

                    # Layer?
                    if not channel_layer_obj.is_channel:
                        # Layers must map to at least 1 channel
                        for channel_id in channels:
                            # Is this a valid channel?
                            channel_obj = ChannelLayer.objects.get(pk=channel_id)
                            if channel_obj:
                                channel_layer_map = {'channel': channel_id, 'layer': channel_layer_obj.pk}
                                map_serializer = ChannelLayerMapSerializer(data=channel_layer_map)
                                if map_serializer.is_valid():
                                    map_serializer.save()

                    # Assign permissions to the users primary group
                    BossPermissionManager.add_permissions_primary_group(self.request.user, channel_layer_obj)

                    # Add Lookup key
                    lookup_key = str(collection_obj.pk) + '&' + str(experiment_obj.pk) + '&' + str(channel_layer_obj.pk)
                    boss_key = collection_obj.name + '&' + experiment_obj.name + '&' + channel_layer_obj.name
                    LookUpKey.add_lookup(lookup_key, boss_key, collection_obj.name, experiment_obj.name,
                                         channel_layer_obj.name)

                    return Response(serializer.data, status=status.HTTP_201_CREATED)
                else:
                    return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT)
            else:
                return BossPermissionError('add', experiment)
        except Collection.DoesNotExist:
            return BossResourceNotFoundError(collection)
        except Experiment.DoesNotExist:
            return BossResourceNotFoundError(experiment)
        except ChannelLayer.DoesNotExist:
            return BossResourceNotFoundError(channel_layer)
        except ValueError:
            return BossHTTPError("Value Error in post data", ErrorCodes.TYPE_ERROR)