def create_observation_image_in_db(api_data, user, conf=None): if IMAGE_FPATH in api_data and IMAGE not in api_data: api_data[IMAGE] = File(open(api_data.pop(IMAGE_FPATH), mode='rb')) if conf is None: conf = {} create_observation_unit = conf.get(CREATE_OBSERVATION_UNITS, None) try: struct = ObservationImageStruct(api_data) except ObservationImageValidationError as error: print('a', error) raise uid = hashlib.sha256(struct.image.read()).hexdigest() struct.image.seek(0) if struct.creation_time: timezone = pytz.timezone(TIME_ZONE) creation_time = timezone.localize( datetime.strptime(struct.creation_time, DATETIME_FORMAT)) else: creation_time = None with transaction.atomic(): observation_unit = _get_or_create_observation_unit( struct, create_observation_unit) study_belongs_to_user = bool( user.groups.filter(name=observation_unit.study.group.name).count()) if not study_belongs_to_user and not is_user_admin(user): msg = 'Can not add observation unit to a study you dont own: {}' msg = msg.format(observation_unit.study.group.name) raise ValueError(msg) try: ObservationImage.objects.get(observation_image_uid=uid) msg = 'This image already exists in db: study {}, accession {}, uid, {}' msg += msg.format(struct.study, struct.accession, uid) raise ValueError(msg) except ObservationImage.DoesNotExist: pass try: observation = ObservationImage.objects.create( observation_image_uid=uid, observation_unit=observation_unit, image=api_data['image'], observer=struct.observer, creation_time=creation_time) except IntegrityError as error: if 'duplicate key value' in str(error): msg = 'This image already exists in db: {}'.format(uid) raise ValueError(msg) raise ValueError(str(error)) except PermissionError as error: raise ValueError(str(error)) except Exception as error: raise ValueError(str(error)) return observation
def update_study_in_db(validated_data, instance, user): study_struct = StudyStruct(api_data=validated_data) if (study_struct.name != instance.name): msg = 'Can not change id in an update operation' raise ValidationError(format_error_message(msg)) group_belong_to_user = bool(user.groups.filter(name=study_struct.metadata.group).count()) if not group_belong_to_user and not is_user_admin(user): msg = 'Can not change ownership if group does not belong to you : {}' msg = msg.format(study_struct.metadata.group) raise ValidationError(format_error_message(msg)) try: group = Group.objects.get(name=study_struct.metadata.group) except Group.DoesNotExist: msg = 'Provided group does not exist in db: {}' msg = msg.format(study_struct.metadata.group) raise ValidationError(format_error_message(msg)) instance.description = study_struct.description instance.is_active = study_struct.is_active instance.group = group instance.is_public = study_struct.metadata.is_public instance.data = study_struct.data instance.start_date = study_struct.start_date instance.end_date = study_struct.end_date instance.save() return instance
def filter_by_permission(task_ids, user): if isinstance(user, AnonymousUser): return [] elif is_user_admin(user): return task_ids else: queryset = UserTasks.objects.filter(user=user, task_id__in=task_ids) return queryset.values_list('task_id', flat=True)
def update_accessionset_in_db(payload, instance, user): struct = AccessionSetStruct(payload) allowed_changes = set(['is_public', 'group']) changes_in_payload = set() if instance.institute.code != struct.institute_code: changes_in_payload.add('institute') if instance.accessionset_number != struct.accessionset_number: changes_in_payload.add('accessionset_number') db_accessions = set([(accession.institute.code, accession.germplasm_number) for accession in instance.accessions.all()]) payload_accessions = set([(accession[INSTITUTE_CODE], accession[GERMPLASM_NUMBER]) for accession in struct.accessions]) are_payload_accessions_diff = bool( db_accessions.difference(payload_accessions)) if are_payload_accessions_diff: changes_in_payload.add('accessions') if instance.is_public != struct.metadata.is_public: changes_in_payload.add('is_public') if instance.group != struct.metadata.group: changes_in_payload.add('group') not_allowed_changes = changes_in_payload.difference(allowed_changes) if not_allowed_changes: msg = "you are not allowed to change accessionsets's: {}" msg = msg.format(','.join(not_allowed_changes)) raise ValidationError(format_error_message(msg)) group_belong_to_user = bool( user.groups.filter(name=struct.metadata.group).count()) if not group_belong_to_user and not is_user_admin(user): msg = 'Can not change ownership if group does not belong to you : {}' msg = msg.format(struct.metadata.group) raise ValidationError(format_error_message(msg)) try: group = Group.objects.get(name=struct.metadata.group) except Group.DoesNotExist: msg = 'Provided group does not exist in db: {}' msg = msg.format(struct.metadata.group) raise ValidationError(format_error_message(msg)) instance.is_public = struct.metadata.is_public instance.owner = group instance.save() return instance
def _add_plants_to_observation_unit(plants, user, observation_unit): for plant in plants: try: plant = Plant.objects.get(name=plant) plant_belongs_to_user = bool(user.groups.filter(name=plant.group.name).count()) if not plant_belongs_to_user and not is_user_admin(user): msg = 'Can not add plant you dont own to observation unit: {}' msg = msg.format(plant.name) raise ValueError(msg) except Plant.DoesNotExist: msg = 'The given plant does not exist in {} : {}' raise ValueError(msg.format(observation_unit.name, plant)) observation_unit.plant_set.add(plant)
def update_accession_in_db(validated_data, instance, user): accession_struct = AccessionStruct(api_data=validated_data) if (accession_struct.institute_code != instance.institute.code or accession_struct.germplasm_number != instance.germplasm_number): msg = 'Can not change id in an update operation' raise ValidationError(format_error_message(msg)) group_belong_to_user = bool(user.groups.filter(name=accession_struct.metadata.group).count()) if not group_belong_to_user and not is_user_admin(user): msg = 'Can not change ownership if group does not belong to you : {}' msg = msg.format(accession_struct.metadata.group) raise ValidationError(format_error_message(msg)) if not is_user_admin(user) and instance.is_public != accession_struct.metadata.is_public: msg = 'User can not make accession public or private' raise ValidationError(format_error_message(msg)) try: group = Group.objects.get(name=accession_struct.metadata.group) except Group.DoesNotExist: msg = 'Provided group does not exist in db: {}' msg = msg.format(accession_struct.metadata.group) raise ValidationError(format_error_message(msg)) with transaction.atomic(): instance.is_available = accession_struct.is_available instance.conservation_status = accession_struct.conservation_status instance.in_nuclear_collection = accession_struct.in_nuclear_collection instance.group = group instance.is_public = accession_struct.metadata.is_public instance.passports.all().delete() for passport_struct in accession_struct.passports: _create_passport_in_db(passport_struct, instance) instance.save() return instance
def create_observation_unit_in_db(api_data, user=None): try: struct = ObservationUnitStruct(api_data) except ObservationUnitValidationError as error: print(error) raise if struct.metadata.group: msg = 'can not set group while creating the observation unit' raise ValueError(msg) try: study = Study.objects.get(name=struct.study) except Study.DoesNotExist: msg = 'The study has not been added yet to the database: ' + struct.study raise ValueError(msg) institute_code = struct.accession[INSTITUTE_CODE] germplasm_number = struct.accession[GERMPLASM_NUMBER] try: accession = Accession.objects.get(institute__code=institute_code, germplasm_number=germplasm_number) except Accession.DoesNotExist: msg = 'The given accessoin is not in db: {} {}'.format(institute_code, germplasm_number) raise ValueError(msg) study_belongs_to_user = bool(user.groups.filter(name=study.group.name).count()) if not study_belongs_to_user and not is_user_admin(user): msg = 'Can not add observation unit to a study you dont own: {}' msg = msg.format(study.group.name) raise ValueError(msg) with transaction.atomic(): try: observation_unit = ObservationUnit.objects.create( name=struct.name, accession=accession, level=struct.level, replicate=struct.replicate, study=study) except IntegrityError: msg = 'This observation unit already exists in db: {}'.format(struct.name) raise ValueError(msg) if struct.plants: _add_plants_to_observation_unit(struct.plants, user, observation_unit) return observation_unit
def filter_queryset(self, queryset): # It filters by the study permissions. And the observations belong # to a observation unit that is in a study queryset = super().filter_queryset(queryset) user = self.request.user if isinstance(user, AnonymousUser): return queryset.filter( observation_unit__study__is_public=True).distinct() elif is_user_admin(user): return queryset else: try: user_groups = user.groups.all() except (IndexError, AttributeError): user_groups = None if user_groups: return queryset.filter( Q(observation_unit__study__is_public=True) | Q(observation_unit__study__group__in=user_groups)) else: return queryset.filter(study__is_public=True)
def update_observation_unit_in_db(validated_data, instance, user): struct = ObservationUnitStruct(api_data=validated_data) if struct.name != instance.name: msg = 'Can not change id in an update operation' raise ValidationError(format_error_message(msg)) try: study = Study.objects.get(name=struct.study) except Study.DoesNotExist: msg = 'The study has not been added yet to the database: ' + struct.study raise ValueError(msg) institute_code = struct.accession[INSTITUTE_CODE] germplasm_number = struct.accession[GERMPLASM_NUMBER] try: accession = Accession.objects.get(institute__code=institute_code, germplasm_number=germplasm_number) except Accession.DoesNotExist: msg = 'The given accessoin is not in db: {} {}'.format(institute_code, germplasm_number) raise ValueError(msg) study_belongs_to_user = bool(user.groups.filter(name=study.group.name).count()) if not study_belongs_to_user and not is_user_admin(user): msg = 'Can not change ownership if study does not belong to you : {}' msg = msg.format(study.group.name) raise ValidationError(format_error_message(msg)) instance.accession = accession instance.level = struct.level instance.replicate = struct.replicate instance.study = study instance.save() plants = [] if struct.plants is None else struct.plants instance.plant_set.clear() _add_plants_to_observation_unit(plants, user, instance) return instance
def filter_queryset(self, queryset): # filter plants by owner and look if they are plublic looing to # the observatins units study tahat they belong to queryset = super().filter_queryset(queryset) user = self.request.user if isinstance(user, AnonymousUser): return queryset.filter( observation_units__study__is_public=True).distinct() elif is_user_admin(user): return queryset else: try: user_groups = user.groups.all() except (IndexError, AttributeError): user_groups = None if user_groups: return queryset.filter( Q(observation_units__study__is_public=True) | Q(group__in=user_groups)).distinct() else: return queryset.filter( observation_units__study__is_public=True).distinct()
def update_observation_in_db(validated_data, instance, user): struct = ObservationStruct(api_data=validated_data) if struct.observation_id != instance.observation_id: msg = 'Can not change id in an update operation' raise ValidationError(format_error_message(msg)) try: observation_variable = ObservationVariable.objects.get(name=struct.observation_variable) except ObservationVariable.DoesNotExist: msg = 'Observation variable {} does not exist in db' msg = msg.format(struct.observation_variable) raise ValueError(msg) try: observation_unit = ObservationUnit.objects.get(name=struct.observation_unit) except ObservationUnit.DoesNotExist: msg = 'Observation unit {} does not exist in db' msg = msg.format(struct.observation_unit) raise ValueError(msg) study_belongs_to_user = bool(user.groups.filter(name=observation_unit.study.group.name).count()) if not study_belongs_to_user and not is_user_admin(user): msg = 'Can not change observation unit because this is in a study you dont own: {}' msg = msg.format(observation_unit.study.name) raise ValueError(msg) if struct.creation_time: timezone = pytz.timezone(TIME_ZONE) creation_time = timezone.localize(datetime.strptime(struct.creation_time, DATETIME_FORMAT)) else: creation_time = None instance.observation_variable = observation_variable instance.observation_unit = observation_unit instance.value = struct.value instance.observer = struct.observer instance.creation_time = creation_time instance.save() return instance
def update_observation_variable_in_db(validated_data, instance, user): struct = ObservationVariableStruct(api_data=validated_data) if struct.name != instance.name: msg = 'Can not change id in an update operation' raise ValidationError(format_error_message(msg)) group_belong_to_user = bool(user.groups.filter(name=struct.metadata.group).count()) if not group_belong_to_user and not is_user_admin(user): msg = 'Can not change ownership if group does not belong to you : {}' msg = msg.format(struct.metadata.group) raise ValidationError(format_error_message(msg)) try: group = Group.objects.get(name=struct.metadata.group) except Group.DoesNotExist: msg = 'Provided group does not exist in db: {}' msg = msg.format(struct.metadata.group) raise ValidationError(format_error_message(msg)) try: scale = Scale.objects.get(name=struct.scale) except Scale.DoesNotExist: raise ValidationError('Scale not valid: ' + struct.scale) try: trait = Trait.objects.get(name=struct.trait) except Trait.DoesNotExist: raise ValidationError('Trait not valid: ' + struct.scale) instance.description = struct.description instance.trait = trait instance.group = group instance.method = struct.method instance.scale = scale instance.save() return instance
def create_observation_in_db(api_data, user, conf=None): if conf is None: conf = {} create_observation_unit = conf.get(CREATE_OBSERVATION_UNITS, None) try: struct = ObservationStruct(api_data) except ObservationValidationError as error: print('a', error) raise try: observation_variable = ObservationVariable.objects.get(name=struct.observation_variable) except ObservationVariable.DoesNotExist: msg = 'Observation variable {} does not exist in db' msg = msg.format(struct.observation_variable) raise ValueError(msg) if struct.creation_time: timezone = pytz.timezone(TIME_ZONE) creation_time = timezone.localize(datetime.strptime(struct.creation_time, DATETIME_FORMAT)) else: creation_time = None try: values = validate_value(str(struct.value), observation_variable) except ValueError as error: if struct.observation_unit: error_row_id = struct.observation_unit elif struct.accession and struct.study: error_row_id = '{} - {}'.format(struct.accession[GERMPLASM_NUMBER], struct.study) else: error_row_id = 'Unknown' msg = '{}: {}'.format(error_row_id, error) raise ValueError(msg) with transaction.atomic(): observations = [] for value in values: observation_unit = _get_or_create_observation_unit(struct, create_observation_unit) study_belongs_to_user = bool(user.groups.filter(name=observation_unit.study.group.name).count()) if not study_belongs_to_user and not is_user_admin(user): msg = 'Can not add observation unit to a study you dont own: {}' msg = msg.format(observation_unit.study.group.name) raise ValueError(msg) try: observation = Observation.objects.create( observation_variable=observation_variable, observation_unit=observation_unit, value=value, observer=struct.observer, creation_time=creation_time) except IntegrityError as error: if 'duplicate key value' in str(error): msg = 'This observation already exists in db' raise ValueError(msg) raise ValueError(str(error)) observations.append(observation) # only when creating by bulk we would have more than one value. # In this cases the values are not returned. In most cases we can return # just the oly one observation if len(observations) == 1: return observations[0] return observations