def moderate_rel_objects(given, status, user = None): """ `given` can either be any model object or a queryset. Moderate given object(s) and all specified related objects. TODO: Permissions must be checked before each iteration. """ from django_monitor import model_from_queue # Not sure how we can find whether `given` is a queryset or object. # Now assume `given` is a queryset/related_manager if it has 'all' if not given: # given may become None. Stop there. return if hasattr(given, 'all'): qset = given.all() for obj in qset: obj.moderate(status, user) model = model_from_queue(qset.model) if model: for rel_name in model['rel_fields']: rel_obj = getattr(obj, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user) else: given.moderate(status, user) model = model_from_queue(given.__class__) if model: for rel_name in model['rel_fields']: rel_obj = getattr(given, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user)
def delete_handler(sender, instance, **kwargs): """ When an instance is deleted, delete corresponding monitor_entries too""" from django_monitor import model_from_queue from django_monitor.models import MonitorEntry from django.contrib.contenttypes.models import ContentType if model_from_queue(sender): me = MonitorEntry.objects.get_for_instance(instance) if me: me.delete() # Delete monitor_entries of parents too monitored_parents = filter( lambda x: model_from_queue(x), instance._meta.parents.keys() ) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = instance._meta.get_ancestor_link(parent) parent_pk = getattr(instance, parent_pk_field.attname) try: me = MonitorEntry.objects.get( content_type = parent_ct, object_id = parent_pk ) me.delete() except MonitorEntry.DoesNotExist: pass
def moderate_rel_objects(given, status, user=None): """ `given` can either be any model object or a queryset. Moderate given object(s) and all specified related objects. TODO: Permissions must be checked before each iteration. """ from django_monitor import model_from_queue # Not sure how we can find whether `given` is a queryset or object. # Now assume `given` is a queryset/related_manager if it has 'all' if not given: # given may become None. Stop there. return if hasattr(given, 'all'): qset = given.all() for obj in qset: obj.moderate(status, user) model = model_from_queue(qset.model) if model: for rel_name in model['rel_fields']: rel_obj = getattr(obj, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user) else: given.moderate(status, user) model = model_from_queue(given.__class__) if model: for rel_name in model['rel_fields']: rel_obj = getattr(given, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user)
def save_handler(sender, instance, **kwargs): """ The following things are done after creating an object in moderated class: 1. Creates monitor entries for object and its parents. 2. Auto-approves object, its parents & specified related objects if user has ``moderate`` permission. Otherwise, they are put in pending. """ import django_monitor from django_monitor.models import MonitorEntry from django.contrib.contenttypes.models import ContentType # Auto-moderation user = get_current_user() opts = instance.__class__._meta mod_perm = '%s.moderate_%s' % ( opts.app_label.lower(), opts.object_name.lower() ) if user and user.has_perm(mod_perm): status = APPROVED_STATUS else: status = PENDING_STATUS # Create corresponding monitor entry if kwargs.get('created', None): me = MonitorEntry.objects.create( status = status, content_object = instance, timestamp = datetime.now() ) me.moderate(status, user) # Create one monitor_entry per moderated parent. monitored_parents = filter( lambda x: django_monitor.model_from_queue(x), instance._meta.parents.keys() ) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = instance._meta.get_ancestor_link(parent) parent_pk = getattr(instance, parent_pk_field.attname) try: me = MonitorEntry.objects.get( content_type = parent_ct, object_id = parent_pk ) except MonitorEntry.DoesNotExist: me = MonitorEntry( content_type = parent_ct, object_id = parent_pk, ) me.moderate(status, user) # Moderate related objects too... model = django_monitor.model_from_queue(instance.__class__) if model: for rel_name in model['rel_fields']: rel_obj = getattr(instance, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user)
def save_handler(sender, instance, **kwargs): """ The following things are done after creating an object in moderated class: 1. Creates monitor entries for object and its parents. 2. Auto-approves object, its parents & specified related objects if user has ``moderate`` permission. Otherwise, they are put in pending. """ import django_monitor from django_monitor.models import MonitorEntry from django.contrib.contenttypes.models import ContentType # Auto-moderation user = get_current_user() opts = instance.__class__._meta mod_perm = '%s.moderate_%s' % (opts.app_label.lower(), opts.object_name.lower()) if user and user.has_perm(mod_perm): status = APPROVED_STATUS else: status = PENDING_STATUS # Create corresponding monitor entry if kwargs.get('created', None): me = MonitorEntry.objects.create(status=status, content_object=instance, timestamp=datetime.now()) me.moderate(status, user) # Create one monitor_entry per moderated parent. monitored_parents = filter( lambda x: django_monitor.model_from_queue(x), instance._meta.parents.keys()) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = instance._meta.get_ancestor_link(parent) parent_pk = getattr(instance, parent_pk_field.attname) try: me = MonitorEntry.objects.get(content_type=parent_ct, object_id=parent_pk) except MonitorEntry.DoesNotExist: me = MonitorEntry( content_type=parent_ct, object_id=parent_pk, ) me.moderate(status, user) # Moderate related objects too... model = django_monitor.model_from_queue(instance.__class__) if model: for rel_name in model['rel_fields']: rel_obj = getattr(instance, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user)
def moderate_related(self, obj, user, status): """Moderate related objects""" model = model_from_queue(obj.__class__) if model: for rel_name in model['rel_fields']: rel_obj = getattr(obj, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user)
def has_delete_permission(self, request, obj = None): """ If ``can_delete_approved`` is set to False in moderation queue and the given object is approved, this will return False. Otherwise, this behaves the same way as the parent class method does. """ model = model_from_queue(self.model) if ( model and (not model['can_delete_approved']) and obj is not None and obj.is_approved ): return False return super(MonitorAdmin, self).has_delete_permission(request, obj)
def delete_handler(sender, instance, **kwargs): """ When an instance is deleted, delete corresponding monitor_entries too""" from django_monitor import model_from_queue from django_monitor.models import MonitorEntry from django.contrib.contenttypes.models import ContentType if model_from_queue(sender): me = MonitorEntry.objects.get_for_instance(instance) if me: me.delete() # Delete monitor_entries of parents too monitored_parents = filter(lambda x: model_from_queue(x), instance._meta.parents.keys()) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = instance._meta.get_ancestor_link(parent) parent_pk = getattr(instance, parent_pk_field.attname) try: me = MonitorEntry.objects.get(content_type=parent_ct, object_id=parent_pk) me.delete() except MonitorEntry.DoesNotExist: pass
def moderate(self, status, user = None, notes = ''): """ developers may use this to moderate objects """ import django_monitor getattr(self, monitor_name).moderate(status, user, notes) # Auto-Moderate parents also monitored_parents = filter( lambda x: django_monitor.model_from_queue(x), self._meta.parents.keys() ) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = self._meta.get_ancestor_link(parent) parent_pk = getattr(self, parent_pk_field.attname) me = MonitorEntry.objects.get( content_type = parent_ct, object_id = parent_pk ) me.moderate(status, user)
def moderate_parents(self, obj, user, status): """Create one monitor_entry per moderated parent""" monitored_parents = filter(lambda x: model_from_queue(x), obj._meta.parents.keys()) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = obj._meta.get_ancestor_link(parent) parent_pk = getattr(obj, parent_pk_field.attname) try: me = MonitorEntry.objects.get(content_type=parent_ct, object_id=parent_pk) except MonitorEntry.DoesNotExist: me = MonitorEntry( content_type=parent_ct, object_id=parent_pk, ) me.moderate(status, user)
def moderate_parents(self, obj, user, status): """Create one monitor_entry per moderated parent""" monitored_parents = filter( lambda x: model_from_queue(x), obj._meta.parents.keys() ) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = obj._meta.get_ancestor_link(parent) parent_pk = getattr(obj, parent_pk_field.attname) try: me = MonitorEntry.objects.get( content_type = parent_ct, object_id = parent_pk ) except MonitorEntry.DoesNotExist: me = MonitorEntry( content_type = parent_ct, object_id = parent_pk, ) me.moderate(status, user)
def moderate_selected(modeladmin, request, queryset, status): """ Generic action to moderate selected objects plus all related objects. """ opts = modeladmin.model._meta # If moderation is disabled.. if not model_from_queue(modeladmin.model): return 0 # Check that the user has required permission for the actual model. # To reset to pending status, change_perm is enough. For all else, # user need to have moderate_perm. if ( (status == PENDING_STATUS and not modeladmin.has_change_permission(request) ) or (status != PENDING_STATUS and not modeladmin.has_moderate_permission(request) ) ): raise PermissionDenied # Approved objects can not further be moderated. queryset = queryset.exclude_approved() # After moderating objects in queryset, moderate related objects also q_count = queryset.count() # We want to use the status display rather than abbreviations in logs. status_display = STATUS_DICT[status] if q_count: #for obj in queryset: #message = 'Changed status from %s to %s.' % ( # obj.get_status_display(), status_display #) #modeladmin.log_moderation(request, obj, message) #me = MonitorEntry.objects.get_for_instance(obj) moderate_rel_objects(queryset, status, request.user) return q_count
def test_1_check_additional_fields(self): """ monitor puts some additional attrs to each moderated class. Let's check for their existence. """ import django_monitor qd_book = django_monitor.model_from_queue(Book) monitor_name = qd_book['monitor_name'] status_name = qd_book['status_name'] self.assertEquals(hasattr(Book, monitor_name), True) self.assertEquals(hasattr(Book, 'monitor_status'), True) self.assertEquals(hasattr(Book, status_name), True) self.assertEquals(hasattr(Book, 'get_monitor_status_display'), True) self.assertEquals(hasattr(Book, 'moderate'), True) self.assertEquals(hasattr(Book, 'approve'), True) self.assertEquals(hasattr(Book, 'challenge'), True) self.assertEquals(hasattr(Book, 'reset_to_pending'), True) self.assertEquals(hasattr(Book, 'is_approved'), True) self.assertEquals(hasattr(Book, 'is_challenged'), True) self.assertEquals(hasattr(Book, 'is_pending'), True) # monitor has changed the default manager, ``objects`` too. self.assertEquals( str(Book.objects)[:34], '<django_monitor.util.CustomManager')
def test_1_check_additional_fields(self): """ monitor puts some additional attrs to each moderated class. Let's check for their existence. """ import django_monitor qd_book = django_monitor.model_from_queue(Book) monitor_name = qd_book['monitor_name'] status_name = qd_book['status_name'] self.assertEquals(hasattr(Book, monitor_name), True) self.assertEquals(hasattr(Book, 'monitor_status'), True) self.assertEquals(hasattr(Book, status_name), True) self.assertEquals(hasattr(Book, 'get_monitor_status_display'), True) self.assertEquals(hasattr(Book, 'moderate'), True) self.assertEquals(hasattr(Book, 'approve'), True) self.assertEquals(hasattr(Book, 'challenge'), True) self.assertEquals(hasattr(Book, 'reset_to_pending'), True) self.assertEquals(hasattr(Book, 'is_approved'), True) self.assertEquals(hasattr(Book, 'is_challenged'), True) self.assertEquals(hasattr(Book, 'is_pending'), True) # monitor has changed the default manager, ``objects`` too. self.assertEquals( str(Book.objects)[:34], '<django_monitor.util.CustomManager' )
def moderate_selected(modeladmin, request, queryset, status): """ Generic action to moderate selected objects plus all related objects. """ # If moderation is disabled.. if not model_from_queue(modeladmin.model): return 0 # Check that the user has required permission for the actual model. # To reset to pending status, change_perm is enough. For all else, # user need to have moderate_perm. if ((status == PENDING_STATUS and not modeladmin.has_change_permission(request)) or (status != PENDING_STATUS and not modeladmin.has_moderate_permission(request))): raise PermissionDenied # Approved objects can not further be moderated. queryset = queryset.exclude_approved() # After moderating objects in queryset, moderate related objects also q_count = queryset.count() # We want to use the status display rather than abbreviations in logs. status_display = STATUS_DICT[status] if q_count: #for obj in queryset: #message = 'Changed status from %s to %s.' % ( # obj.get_status_display(), status_display #) #modeladmin.log_moderation(request, obj, message) #me = MonitorEntry.objects.get_for_instance(obj) moderate_rel_objects(queryset, status, request.user) return q_count
def is_monitored(self): """Returns whether the underlying model is monitored or not.""" return bool(model_from_queue(self.model))
def save_handler(sender, instance, **kwargs): """ The following things are done after creating an object in moderated class: 1. Creates monitor entries for object and its parents. 2. Auto-approves object, its parents & specified related objects if user has ``moderate`` permission. Otherwise, they are put in pending. """ import django_monitor # Auto-moderation user = get_current_user() opts = instance.__class__._meta mod_perm = '%s.moderate_%s' % ( opts.app_label.lower(), opts.object_name.lower() ) if user and user.has_perm(mod_perm): status = APPROVED_STATUS else: status = PENDING_STATUS # Create corresponding monitor entry if kwargs.get('created', None): from django_monitor import _queue me = MonitorEntry.objects.create( status = status, content_object = instance, timestamp = datetime.now() ) me.moderate(status, user) # Create one monitor_entry per moderated parent. monitored_parents = filter( lambda x: django_monitor.model_from_queue(x), instance._meta.parents.keys() ) for parent in monitored_parents: parent_ct = ContentType.objects.get_for_model(parent) parent_pk_field = instance._meta.get_ancestor_link(parent) parent_pk = getattr(instance, parent_pk_field.attname) try: me = MonitorEntry.objects.get( content_type = parent_ct, object_id = parent_pk ) except MonitorEntry.DoesNotExist: me = MonitorEntry( content_type = parent_ct, object_id = parent_pk, ) me.moderate(status, user) # Moderate related objects too... model = django_monitor.model_from_queue(instance.__class__) if model: for rel_name in model['rel_fields']: rel_obj = getattr(instance, rel_name, None) if rel_obj: moderate_rel_objects(rel_obj, status, user) if callable(_queue[instance.__class__]['notify_moderators']): if not _queue[instance.__class__]['notify_moderators'](instance): return if MODERATOR_LIST: from django.contrib.sites.models import Site domain = Site.objects.get(id=settings.SITE_ID).domain status = me.get_status_display() instance_class = instance.__class__.__name__ app_label = instance._meta.app_label long_desc = _queue[instance.__class__]['long_desc'] # message message = _long_desc(instance, long_desc) if status == 'Pending': message += "\n\nTo moderate, go to http://%s%s?ot=desc&status=IP&o=2" % (domain, reverse('admin:%s_%s_changelist' % (app_label, instance_class.lower()))) # subject key = "%s:%s" % (instance_class, status) # if me.moderation_status_by and me.moderation_status_by.username == 'gatekeeper_automod': # key = "%s:auto" % key subject = "[%s] New monitor object on %s" % (key, domain) # sender from_addr = settings.DEFAULT_FROM_EMAIL send_mail(subject, message, from_addr, MODERATOR_LIST, fail_silently=True)