def delete(self, *args, **kwargs): if self.recipient_count() > 0: raise ProtectedError("BadgeClass may only be deleted if all BadgeInstances have been revoked.", self) if self.pathway_element_count() > 0: raise ProtectedError("BadgeClass may only be deleted if all PathwayElementBadge have been removed.", self) if len(self.cached_completion_elements()) > 0: raise ProtectedError("Badge could not be deleted. It is being used as a pathway completion badge.", self) issuer = self.issuer super(BadgeClass, self).delete(*args, **kwargs) issuer.publish()
def disable(self): if self.disabled: raise ProtectedError(gettext('This question is already disabled.'), [self]) if PollFormLineCondition.objects.filter(source=self).exists(): raise ProtectedError(gettext('There is at least one other question ' 'which depends on this question.' ), [self], ) self.disabled = True self.conditions.all().delete() self.save()
def delete(self, *args, **kwargs): """ Recursive delete function that - deletes all children - only publishes the parent of the initially deleted entity - removes all associated staff memberships without publishing the associated object (the one that is deleted) """ publish_parent = kwargs.pop('publish_parent', True) if self.assertions: raise ProtectedError( "{} may only be deleted if there are no awarded Assertions.". format(self.__class__.__name__), self) try: # first the children kids = self.children for child in kids: child.delete(publish_parent=False) except AttributeError: # no kids pass for membership in self.staff_items: membership.delete(publish_object=False) ret = super(PermissionedModelMixin, self).delete(*args, **kwargs) if publish_parent: try: self.parent.publish() except AttributeError: # no parent pass return ret
def protect_news_group_all(sender, instance, using, **kwargs): if instance.title != settings.NEWS_GROUP_ALL_TITLE: pass else: raise ProtectedError(protected_objects=instance, msg='دستۀ «' + settings.NEWS_GROUP_ALL_TITLE + '» را نمیتوان حذف کرد.')
def delete(self, *args, **kwargs): if self.recipient_count() > 0: raise ProtectedError("BadgeClass may only be deleted if all BadgeInstances have been revoked.") issuer = self.issuer super(BadgeClass, self).delete(*args, **kwargs) issuer.publish()
def delete(self, *args, **kwargs): if self.recipient_count > 0: raise ProtectedError( "Issuer can not be deleted because it has previously issued badges.", self) # remove any unused badgeclasses owned by issuer for bc in self.cached_badgeclasses(): bc.delete() staff = self.cached_issuerstaff() ret = super(Issuer, self).delete(*args, **kwargs) # remove membership records for membership in staff: membership.delete(publish_issuer=False) if apps.is_installed('badgebook'): # badgebook shim try: from badgebook.models import LmsCourseInfo # update LmsCourseInfo's that were using this issuer as the default_issuer for course_info in LmsCourseInfo.objects.filter( default_issuer=self): course_info.default_issuer = None course_info.save() except ImportError: pass return ret
def db_for_write(self, model, **hints): """ Prevent write access to the coursera database. """ raise ProtectedError( "No write access to 'coursera' database.", [hints.get("instance")] )
def check_detail_configuration(brick_id: str): locations = BrickDetailviewLocation.objects.filter(brick_id=brick_id) if locations: def get_message(): for loc in locations: if loc.content_type is None: return gettext( 'This block is used in the default detail-view configuration' ) for loc in locations: if not loc.superuser and loc.role is None: return gettext( 'This block is used in the detail-view configuration of «{model}»' ).format(model=loc.content_type) for loc in locations: if loc.superuser: return gettext( 'This block is used in the detail-view configuration ' 'of «{model}» for superusers' ).format(model=loc.content_type) for loc in locations: if loc.role is not None: return gettext( 'This block is used in the detail-view configuration ' 'of «{model}» for role «{role}»' ).format(model=loc.content_type, role=loc.role) return 'This block is used in a detail-view configuration (unexpected case)' raise ProtectedError(get_message(), [*locations])
def delete(self): if self.ingredient_set.all().exclude(step=None).count() > 0: raise ProtectedError( self.name + _(" is part of a recipe step and cannot be deleted"), self.ingredient_set.all().exclude(step=None)) else: return super().delete()
def delete(self, *args, **kwargs): if not self.disabled and PollFormLineCondition.objects.filter(source=self).exists(): raise ProtectedError(gettext('There is at least one other ' 'question which depends on this question.' ), [self], ) super().delete(*args, **kwargs)
def delete(self, *args, **kwargs): # pylint: disable=arguments-differ """ Delete this email notification channel. """ if not self.shared: newrelic.delete_email_notification_channel(self.id) super().delete(*args, **kwargs) else: raise ProtectedError('Cannot delete a shared email notification channel', self)
def protect_emailuserhandler_to_ident_field(sender, instance, raw, **kwargs): from django.db.models import ProtectedError for child in instance.parent_form.depth_first_order(): if isinstance(child, EmailUserHandler) and child.to_ident == instance.ident: raise ProtectedError( "This cannot be deleted because it is being referenced by a %s." % (child.display_name, ), [child])
def delete(self, *args, **kwargs): """Deletes a user instance. Trying to delete a meta user raises the `ProtectedError` exception. """ if self.is_meta: raise ProtectedError('Cannot remove meta user instances', None) super(User, self).delete(*args, **kwargs)
def delete(self, *args, **kwargs): if len(self.cached_badgeclasses()) > 0: raise ProtectedError("Issuer may only be deleted after all its defined BadgeClasses have been deleted.") staff = self.cached_staff() owner = self.owner super(Issuer, self).delete(*args, **kwargs) owner.publish() for member in staff: member.publish()
def prevent_deletion_if_in_use(sender, instance, **kwargs): if isinstance(instance, (AbstractIonDocument, AbstractIonImage, AbstractIonMedia)): usage = instance.get_usage() if usage: model_name = instance.__class__.__name__ raise ProtectedError( f"Cannot delete instance of model '{model_name}' because it is referenced in stream field blocks", usage, )
def prevent_slide_deletion(sender, instance, using, **_): del sender, using date_send = instance.sent if date_send: date_now = datetime.now(timezone.utc) if (date_now - date_send) < timedelta(days=21): raise ProtectedError( 'Slides must be stored for 21 days due to legal requirements', instance)
def protect_containers(sender, instance, using, **kwargs): '''The root (container) may not be deleted. If a container is deleted, it's modules are moved to the parent. ''' # Don't allow delete of the root container if not instance.parent: raise ProtectedError('A root container may not be deleted') # Move any modules belonging to the container to parent container. for module in instance.module_set.all(): module.container = instance.parent module.save()
def delete(self, *args, **kwargs): # Check for LAG interfaces split across member chassis interfaces = Interface.objects.filter( device__in=self.members.all(), lag__isnull=False).exclude(lag__device=F('device')) if interfaces: raise ProtectedError( f"Unable to delete virtual chassis {self}. There are member interfaces which form a cross-chassis LAG", interfaces) return super().delete(*args, **kwargs)
def test_protected_error() -> None: response = exception_handler( ProtectedError("Resource 'Hedgehog' has dependencies.", protected_objects=[1])) assert response is not None assert response.status_code == status.HTTP_409_CONFLICT assert response.data == { "type": "invalid_request", "code": "protected_error", "detail": "Requested operation cannot be completed because" " a related object is protected.", "attr": None, }
def process_obj(self, obj, cascade_type, related_column): if cascade_type == "SET_NULL": setattr(obj, related_column, None) obj.save() elif cascade_type == "CASCADE": if hasattr(obj, "soft_delete"): obj.soft_delete() else: obj.delete() elif cascade_type == "PROTECT": raise ProtectedError("", related_column) else: raise NotImplementedError()
def delete(self, *args, **kwargs): from ..utils import SectionTree section_id = self.id for node in SectionTree(self.pform): if node.is_section and node.id == section_id: if not node.has_line: break raise ProtectedError( gettext('There is at least one question in this section.'), [self], ) super().delete(*args, **kwargs)
def delete(self, **kwargs): # Do not allow deletion if this dataset is referenced by other datasets linking_fields = ReferenceDatasetField.objects.filter( linked_reference_dataset=self ) if linking_fields.count() > 0: raise ProtectedError( 'Cannot delete reference dataset as it is linked to by other datasets', set(x.reference_dataset for x in linking_fields), ) # Delete external table when ref dataset is deleted if self.external_database is not None: self._drop_external_database_table(self.external_database.memorable_name) super().delete(**kwargs)
def check_on_going_upload(sender, instance, **kwargs): if instance.status == AssetUpload.Status.IN_PROGRESS: logger.error( "Cannot delete asset %s due to upload %s which is still in progress", instance.asset.name, instance.upload_id, extra={ 'upload_id': instance.upload_id, 'asset': instance.asset.name, 'item': instance.asset.item.name, 'collection': instance.asset.item.collection.name }) raise ProtectedError( f"Asset {instance.asset.name} has still an upload in progress", [instance])
def process_queryset(self, related_manager, cascade_type, related_column): data = {related_column: None} queryset = related_manager.all() if cascade_type == "SET_NULL": related_manager.update(**data) elif cascade_type == "CASCADE": if isinstance(queryset, SoftDeleteQuerySet): queryset.soft_delete() else: queryset.delete() elif cascade_type == "PROTECT": if queryset.count() > 0: raise ProtectedError("", related_column) else: raise NotImplementedError()
def delete(self, *args, **kwargs): """Deletes a user instance. Trying to delete a meta user raises the `ProtectedError` exception. """ if self.is_meta: raise ProtectedError('Cannot remove meta user instances', None) purge = kwargs.pop("purge", False) if purge: UserPurger(self).purge() else: UserMerger(self, User.objects.get_nobody_user()).merge() super(User, self).delete(*args, **kwargs)
def check_mypage_configuration(brick_id: str): locations = BrickMypageLocation.objects.filter(brick_id=brick_id) if locations: if any(mpl.user is None for mpl in locations): msg = gettext( 'This block is used in the default configuration for "My page"' ) else: for mpl in locations: if mpl.user: msg = gettext( 'This block is used in the configuration of «{}» for "My page"' ).format(mpl.user) break else: msg = 'This block is used in the "My page" configuration (unexpected case)' raise ProtectedError(msg, [*locations])
def _on_delete(self): for relation in self._meta._relation_tree: on_delete = getattr(relation.remote_field, 'on_delete') if on_delete in [None, models.DO_NOTHING]: continue filter = {relation.name: self} related_queryset = relation.model.objects.filter(**filter) if on_delete == models.CASCADE: relation.model.objects.filter(**filter).delete() elif on_delete == models.SET_NULL: for r in related_queryset.all(): related_queryset.update(**{relation.name: None}) elif on_delete == models.PROTECT: if related_queryset.count() > 0: raise ProtectedError('Cannot remove this instances', related_queryset.all()) else: raise NotImplementedError()
def test_delete_protected_folder(rf, admin_user): shop = get_default_shop() folder1 = get_or_create_folder(shop, printable_gibberish(), admin_user) folder2 = get_or_create_folder(shop, printable_gibberish(), admin_user) folder2.parent = folder1 folder2.save() with mock.patch( "filer.models.foldermodels.Folder.delete", side_effect=ProtectedError("Cannot delete", [folder2]), ) as mocked: mbv_command(admin_user, {"action": "delete_folder", "id": folder2.pk}) mocked.assert_called() folder1 = Folder.objects.get(pk=folder1.pk) assert list(folder1.get_children()) == [folder2] mbv_command(admin_user, {"action": "delete_folder", "id": folder2.pk}) folder1 = Folder.objects.get(pk=folder1.pk) assert list(folder1.get_children()) == [] assert not Folder.objects.filter(pk=folder2.pk).exists()
def post(self, request, **kwargs): #post delete the obj obj = self.get_object(kwargs) form = ComfirmationForm(request.POST) if form.is_valid(): try: obj.delete() except ProtectedError: raise ProtectedError( self.model, "the obj can't delete, because the model is protected!") msg = "Deleted {} {}".format(self.model._meta.verbose_name, obj) messages.success(request, msg) return redirect(self.get_return_url(request, obj)) return render( request, self.template_name, { 'obj': obj, 'form': form, 'obj_type': self.model._meta.verbose_name, 'return_url': self.get_return_url(request, obj), })
def check_home_configuration(brick_id: str): locations = BrickHomeLocation.objects.filter(brick_id=brick_id) if locations: if any(not hl.superuser and hl.role is None for hl in locations): msg = gettext( 'This block is used in the default Home configuration' ) elif any(hl.superuser for hl in locations): msg = gettext( 'This block is used in the Home configuration for superusers' ) else: for hl in locations: if hl.role: msg = gettext( 'This block is used in the Home configuration of role «{}»' ).format(hl.role) break else: msg = 'This block is used in the Home configuration (unexpected case)' raise ProtectedError(msg, [*locations])