def get(self, request, collection): """ Get a single instance of a collection Args: request: DRF Request object collection: Collection name specifying the collection you want Returns: Collection """ try: collection_obj = Collection.objects.get(name=collection) # Check for permissions if collection_obj is None: return BossResourceNotFoundError(collection) if collection_obj.public or request.user.has_perm( "read", collection_obj): if collection_obj.to_be_deleted is not None: return BossHTTPError( "Invalid Request. This Resource has been marked for deletion", ErrorCodes.RESOURCE_MARKED_FOR_DELETION) serializer = CollectionSerializer(collection_obj) data = serializer.data data['experiments'] = serializer.get_experiments_permissions( collection_obj, request.user) return Response(data, status=200) else: return BossPermissionError('read', collection) except Collection.DoesNotExist: return BossResourceNotFoundError(collection)
def get(self, request, collection, experiment, channel): """ Retrieve information about a channel. Args: request: DRF Request object collection: Collection name experiment: Experiment name channel: Channel name Returns : Channel """ try: 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) # Check for permissions if request.user.has_perm("read", channel_obj): if channel_obj.to_be_deleted is not None: return BossHTTPError("Invalid Request. This Resource has been marked for deletion", ErrorCodes.RESOURCE_MARKED_FOR_DELETION) serializer = ChannelReadSerializer(channel_obj) return Response(serializer.data) else: return BossPermissionError('read', channel) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment) except Channel.DoesNotExist: return BossResourceNotFoundError(channel) except ValueError: return BossHTTPError("Value Error in post data", ErrorCodes.TYPE_ERROR)
def delete(self, request, collection, experiment): """ Delete a experiment Args: request: DRF Request object collection: Name of collection experiment: Experiment name to delete Returns: Http status """ try: collection_obj = Collection.objects.get(name=collection) experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj) if request.user.has_perm("delete", experiment_obj): experiment_obj.delete() # # get the lookup key and delete all the meta data for this object # bosskey = collection + '&' + experiment # lkey = LookUpKey.get_lookup_key(bosskey) # mdb = MetaDB() # mdb.delete_meta_keys(lkey) # delete the lookup key for this object LookUpKey.delete_lookup_key(collection, experiment, None) return HttpResponse(status=204) else: return BossPermissionError('delete', experiment) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment) except ProtectedError: return BossHTTPError("Cannot delete {}. It has channels or layers that reference " "it.".format(experiment), ErrorCodes.INTEGRITY_ERROR)
def get(self, request, collection, experiment, channel_layer): """ Retrieve information about a channel. Args: request: DRF Request object collection: Collection name experiment: Experiment name channel_layer: Channel or Layer name Returns : ChannelLayer """ try: collection_obj = Collection.objects.get(name=collection) experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj) channel_layer_obj = ChannelLayer.objects.get(name=channel_layer, experiment=experiment_obj) # Check for permissions if request.user.has_perm("read", channel_layer_obj): serializer = ChannelLayerSerializer(channel_layer_obj) return Response(serializer.data) else: return BossPermissionError('read', channel_layer) 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)
def get(self, request, collection, experiment): """ GET requests for a single instance of a experiment Args: request: DRF Request object collection: Collection name specifying the collection you want experiment: Experiment name specifying the experiment instance Returns : Experiment """ try: collection_obj = Collection.objects.get(name=collection) experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj) # Check for permissions if request.user.has_perm("read", experiment_obj): if experiment_obj.to_be_deleted is not None: return BossHTTPError("Invalid Request. This Resource has been marked for deletion", ErrorCodes.RESOURCE_MARKED_FOR_DELETION) serializer = ExperimentReadSerializer(experiment_obj) return Response(serializer.data) else: return BossPermissionError('read', experiment) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment)
def delete(self, request, collection, experiment, channel_layer): """ Delete a Channel or a Layer Args: request: DRF Request object collection: Collection name experiment: Experiment name channel_layer: Channel or Layer name Returns : Http status """ try: collection_obj = Collection.objects.get(name=collection) experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj) channel_layer_obj = ChannelLayer.objects.get(name=channel_layer, experiment=experiment_obj) if request.user.has_perm("delete", channel_layer_obj): channel_layer_obj.delete() # delete the lookup key for this object LookUpKey.delete_lookup_key(collection, experiment, channel_layer) return HttpResponse(status=204) else: return BossPermissionError('delete', channel_layer) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment) except ChannelLayer.DoesNotExist: return BossResourceNotFoundError(channel_layer) except ProtectedError: return BossHTTPError("Cannot delete {}. It has layers that reference it.".format(channel_layer), ErrorCodes.INTEGRITY_ERROR)
def delete(self, request, collection, experiment): """ Delete a experiment Args: request: DRF Request object collection: Name of collection experiment: Experiment name to delete Returns: Http status """ try: collection_obj = Collection.objects.get(name=collection) experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj) if request.user.has_perm("delete", experiment_obj): # Are there channels that reference it serializer = ExperimentReadSerializer(experiment_obj) if len(serializer.get_valid_channels(experiment_obj)) > 0: # This experiment has channels that reference it and cannot be deleted return BossHTTPError(" Experiment {} has channels that reference it and cannot be deleted." "Please delete the channels first.".format(experiment), ErrorCodes.INTEGRITY_ERROR) experiment_obj.to_be_deleted = datetime.now() experiment_obj.save() return HttpResponse(status=204) else: return BossPermissionError('delete', experiment) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment) except ProtectedError: return BossHTTPError("Cannot delete {}. It has channels that reference it." .format(experiment), ErrorCodes.INTEGRITY_ERROR)
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)
def put(self, request, collection, experiment): """ Update a experiment using django rest framework Args: request: DRF Request object collection: Collection name experiment : Experiment name for the new experiment Returns: Experiment """ try: # Check if the object exists collection_obj = Collection.objects.get(name=collection) experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj) if request.user.has_perm("update", experiment_obj): serializer = ExperimentUpdateSerializer(experiment_obj, data=request.data, partial=True) if serializer.is_valid(): serializer.save() # update the lookup key if you update the name if 'name' in request.data and request.data[ 'name'] != experiment: lookup_key = str(collection_obj.pk) + '&' + str( experiment_obj.pk) boss_key = collection_obj.name + '&' + request.data[ 'name'] LookUpKey.update_lookup_experiment( lookup_key, boss_key, collection_obj.name, request.data['name']) # return the object back to the user experiment = serializer.data['name'] experiment_obj = Experiment.objects.get( name=experiment, collection=collection_obj) serializer = ExperimentReadSerializer(experiment_obj) return Response(serializer.data) else: return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT) else: return BossPermissionError('update', experiment) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment) except BossError as err: return err.to_http()
def delete(self, request, coordframe): """ Delete a coordinate frame Args: request: DRF Request object coordframe: Name of coordinateframe to delete Returns: Http status """ try: coordframe_obj = CoordinateFrame.objects.get(name=coordframe) if request.user.has_perm("delete", coordframe_obj): # Are there experiments that reference it serializer = CoordinateFrameDeleteSerializer(coordframe_obj) if len(serializer.get_valid_exps(coordframe_obj)) > 0: # This collection has experiments that reference it and cannot be deleted return BossHTTPError(" Coordinate frame {} has experiments that reference it and cannot be deleted." "Please delete the experiments first.".format(coordframe), ErrorCodes.INTEGRITY_ERROR) coordframe_obj.to_be_deleted = datetime.now() coordframe_obj.save() return HttpResponse(status=204) else: return BossPermissionError('delete', coordframe) except CoordinateFrame.DoesNotExist: return BossResourceNotFoundError(coordframe) except ProtectedError: return BossHTTPError("Cannot delete {}. It has experiments that reference it.".format(coordframe), ErrorCodes.INTEGRITY_ERROR)
def put(self, request, collection): """ Update a collection using django rest framework Args: request: DRF Request object collection: Collection name Returns: Collection """ try: # Check if the object exists collection_obj = Collection.objects.get(name=collection) # Check for permissions if request.user.has_perm("update", collection_obj): serializer = CollectionSerializer(collection_obj, data=request.data, partial=True) if serializer.is_valid(): serializer.save() # update the lookup key if you update the name if 'name' in request.data and request.data['name'] != collection: lookup_key = str(collection_obj.pk) boss_key = request.data['name'] LookUpKey.update_lookup(lookup_key, boss_key, request.data['name']) return Response(serializer.data) else: return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT) else: return BossPermissionError('update', collection) except Collection.DoesNotExist: return BossResourceNotFoundError(collection)
def put(self, request, coordframe): """ Update a coordinate frame using django rest framework Args: request: DRF Request object coordframe: Coordinate frame name Returns: CoordinateFrame """ try: # Check if the object exists coordframe_obj = CoordinateFrame.objects.get(name=coordframe) if request.user.has_perm("update", coordframe_obj): serializer = CoordinateFrameUpdateSerializer(coordframe_obj, data=request.data, partial=True) if serializer.is_valid(): serializer.save() # return the object back to the user coordframe = serializer.data['name'] coordframe_obj = CoordinateFrame.objects.get(name=coordframe) serializer = CoordinateFrameSerializer(coordframe_obj) return Response(serializer.data) else: return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT) else: return BossPermissionError('update', coordframe) except CoordinateFrame.DoesNotExist: return BossResourceNotFoundError(coordframe)
def put(self, request, collection, experiment, channel_layer): """ Update new Channel or Layer 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() if 'is_channel' in channel_layer_data: channel_layer_data['is_channel'] = self.get_bool(channel_layer_data['is_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_layer_obj = ChannelLayer.objects.get(name=channel_layer, experiment=experiment_obj) if request.user.has_perm("update", channel_layer_obj): serializer = ChannelLayerSerializer(channel_layer_obj, data=request.data, partial=True) if serializer.is_valid(): serializer.save() # update the lookup key if you update the name if 'name' in request.data and request.data['name'] != channel_layer: lookup_key = str(collection_obj.pk) + '&' + str(experiment_obj.pk) + '&' \ + str(channel_layer_obj.pk) boss_key = collection_obj.name + '&' + experiment_obj.name + '&' + request.data['name'] LookUpKey.update_lookup(lookup_key, boss_key, collection_obj.name, experiment_obj.name, request.data['name']) return Response(serializer.data) else: return BossHTTPError("{}".format(serializer.errors), ErrorCodes.INVALID_POST_ARGUMENT) else: return BossPermissionError('update', channel_layer) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment) except ChannelLayer.DoesNotExist: return BossResourceNotFoundError(channel_layer)
def delete(self, request, collection, experiment, channel): """ Delete a Channel Args: request: DRF Request object collection: Collection name experiment: Experiment name channel: Channel name Returns : Http status """ try: 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("delete", channel_obj): # The channel cannot be deleted if this is the source of any other channels derived_channels = channel_obj.get_derived() if len(derived_channels) > 0: return BossHTTPError( "Channel {} is the source channel of other channels and cannot be deleted" .format(channel), ErrorCodes.INTEGRITY_ERROR) channel_obj.to_be_deleted = timezone.now() channel_obj.save() return HttpResponse(status=204) else: return BossPermissionError('delete', channel) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment) except Channel.DoesNotExist: return BossResourceNotFoundError(channel) except ProtectedError: return BossHTTPError( "Cannot delete {}. It has channels that reference it.".format( channel), ErrorCodes.INTEGRITY_ERROR)
def get(self, request, collection, experiment): """ GET requests for a single instance of a experiment Args: request: DRF Request object collection: Collection name specifying the collection you want experiment: Experiment name specifying the experiment instance Returns : Experiment """ try: collection_obj = Collection.objects.get(name=collection) experiment_obj = Experiment.objects.get(name=experiment, collection=collection_obj) # Check for permissions if request.user.has_perm("read", experiment_obj): serializer = ExperimentSerializer(experiment_obj) return Response(serializer.data) else: return BossPermissionError('read', experiment) except Collection.DoesNotExist: return BossResourceNotFoundError(collection) except Experiment.DoesNotExist: return BossResourceNotFoundError(experiment)
def get(self, request, coordframe): """ GET requests for a single instance of a coordinateframe Args: request: DRF Request object coordframe: Coordinate frame name specifying the coordinate frame you want Returns: CoordinateFrame """ try: coordframe_obj = CoordinateFrame.objects.get(name=coordframe) serializer = CoordinateFrameSerializer(coordframe_obj) return Response(serializer.data) except CoordinateFrame.DoesNotExist: return BossResourceNotFoundError(coordframe)
def get(self, request, coordframe): """ GET requests for a single instance of a coordinateframe Args: request: DRF Request object coordframe: Coordinate frame name specifying the coordinate frame you want Returns: CoordinateFrame """ try: coordframe_obj = CoordinateFrame.objects.get(name=coordframe) if coordframe_obj.to_be_deleted is not None: return BossHTTPError("Invalid Request. This Resource has been marked for deletion", ErrorCodes.RESOURCE_MARKED_FOR_DELETION) serializer = CoordinateFrameSerializer(coordframe_obj) return Response(serializer.data) except CoordinateFrame.DoesNotExist: return BossResourceNotFoundError(coordframe)
def delete(self, request, coordframe): """ Delete a coordinate frame Args: request: DRF Request object coordframe: Name of coordinateframe to delete Returns: Http status """ try: coordframe_obj = CoordinateFrame.objects.get(name=coordframe) if request.user.has_perm("delete", coordframe_obj): coordframe_obj.delete() return HttpResponse(status=204) else: return BossPermissionError('delete', coordframe) except CoordinateFrame.DoesNotExist: return BossResourceNotFoundError(coordframe) except ProtectedError: return BossHTTPError("Cannot delete {}. It has experiments that reference it.".format(coordframe), ErrorCodes.INTEGRITY_ERROR)
def get(self, request, collection): """ Get a single instance of a collection Args: request: DRF Request object collection: Collection name specifying the collection you want Returns: Collection """ try: collection_obj = Collection.objects.get(name=collection) # Check for permissions if request.user.has_perm("read", collection_obj): serializer = CollectionSerializer(collection_obj) return Response(serializer.data, status=200) else: return BossPermissionError('read', collection) except Collection.DoesNotExist: return BossResourceNotFoundError(collection)
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)
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)
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): # The source and related channels are names and need to be removed from the dict before serialization source_channels = request.data.pop('sources', []) related_channels = request.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=request.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 request.data and request.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 + '&' + request.data['name'] LookUpKey.update_lookup(lookup_key, boss_key, collection_obj.name, experiment_obj.name, request.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)
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)