diff --git a/django/contrib/comments/admin.py b/django/contrib/comments/admin.py
index 3b1fb14..fda2651 100644
--- a/django/contrib/comments/admin.py
+++ b/django/contrib/comments/admin.py
@@ -1,7 +1,7 @@
 from django.contrib import admin
-from django.contrib.comments.models import Comment
+from django.contrib.comments.models import Comment, CommentFlag
 from django.utils.translation import ugettext_lazy as _
-from django.contrib.comments import get_model
+from django.contrib.comments import get_model, signals
 
 class CommentsAdmin(admin.ModelAdmin):
     fieldsets = (
@@ -21,6 +21,64 @@ class CommentsAdmin(admin.ModelAdmin):
     date_hierarchy = 'submit_date'
     ordering = ('-submit_date',)
     search_fields = ('comment', 'user__username', 'user_name', 'user_email', 'user_url', 'ip_address')
+    actions = ['approve', 'remove']
+
+    def approve(self, request, queryset):
+        """ Approve comments through moderation. """
+        cnt = 0
+        for comment in queryset:
+            # Flag the comment as approved.
+            flag, created = CommentFlag.objects.get_or_create(
+                comment = comment,
+                user    = request.user,
+                flag    = CommentFlag.MODERATOR_APPROVAL
+            )
+
+            comment.is_removed = False
+            comment.is_public = True
+            comment.save()
+
+            signals.comment_was_flagged.send(
+                sender  = comment.__class__,
+                comment = comment,
+                flag    = flag,
+                created = created,
+                request = request
+            )
+            cnt += 1
+        self.message_user(request, '%s successfully approved.' % self._get_message_bit(cnt))
+    approve.short_description = 'Approve selected comments'
+
+    def remove(self, request, queryset):
+        """ Remove comments through moderation. """
+        cnt = 0
+        for comment in queryset:
+            # Flag the comment as removed.
+            flag, created = CommentFlag.objects.get_or_create(
+                comment = comment,
+                user    = request.user,
+                flag    = CommentFlag.MODERATOR_DELETION
+            )
+
+            comment.is_removed = True
+            comment.save()
+
+            signals.comment_was_flagged.send(
+                sender  = comment.__class__,
+                comment = comment,
+                flag    = flag,
+                created = created,
+                request = request
+            )
+            cnt += 1
+        self.message_user(request, '%s successfully removed.' % self._get_message_bit(cnt))
+    remove.short_description = 'Remove selected comments'
+
+    def _get_message_bit(self, rows_updated):
+        if rows_updated == 1:
+            return '1 comment was'
+        else:
+            return '%s comments were' % rows_updated
 
 # Only register the default admin if the model is the built-in comment model
 # (this won't be true if there's a custom comment app).
diff --git a/tests/regressiontests/comment_tests/tests/__init__.py b/tests/regressiontests/comment_tests/tests/__init__.py
index 449fea4..b2ead81 100644
--- a/tests/regressiontests/comment_tests/tests/__init__.py
+++ b/tests/regressiontests/comment_tests/tests/__init__.py
@@ -87,3 +87,4 @@ from regressiontests.comment_tests.tests.templatetag_tests import *
 from regressiontests.comment_tests.tests.comment_view_tests import *
 from regressiontests.comment_tests.tests.moderation_view_tests import *
 from regressiontests.comment_tests.tests.comment_utils_moderators_tests import *
+from regressiontests.comment_tests.tests.admin_moderation_tests import *
diff --git a/tests/regressiontests/comment_tests/tests/admin_moderation_tests.py b/tests/regressiontests/comment_tests/tests/admin_moderation_tests.py
new file mode 100644
index 0000000..24a1c74
--- /dev/null
+++ b/tests/regressiontests/comment_tests/tests/admin_moderation_tests.py
@@ -0,0 +1,66 @@
+from django.contrib.comments.models import Comment, CommentFlag
+from regressiontests.comment_tests.tests import CommentTestCase
+from django.contrib.comments import signals
+from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
+
+class AdminModerationTests(CommentTestCase):
+    fixtures = ['comment_tests', 'admin-views-users.xml']
+
+    def setUp(self):
+        self.client.login(username='super', password='secret')
+
+    def tearDown(self):
+        self.client.logout()
+
+    def test_comment_admin_approve_action(self):
+        "Tests the builtin aprove action defined as an admin method."
+        c1, c2, c3, c4 = self.createSomeComments()
+        c1.is_public = False
+        c1.is_removed = True
+        c1.save()
+        action_data = {
+            ACTION_CHECKBOX_NAME: [1],
+            'action' : 'approve',
+            'index' : c1.pk,
+        }
+        response = self.client.post('/admin/comments/comment', action_data)
+        c = Comment.objects.get(pk=c1.pk)
+        self.assertTrue(c.is_public)
+        self.assertFalse(c.is_removed)
+        self.assertEqual(c.flags.filter(flag=CommentFlag.MODERATOR_APPROVAL, user__username="super").count(), 1)
+
+    def test_approve_action_signals(self):
+        "Test signal is received upon aprove action."
+        def receive(sender, **kwargs):
+            received_signals.append(kwargs.get('signal'))
+
+        received_signals = []
+        signals.comment_was_flagged.connect(receive)
+
+        self.test_comment_admin_approve_action()
+        self.assertEqual(received_signals, [signals.comment_was_flagged])
+    
+    def test_comment_admin_remove_action(self):
+        "Tests the builtin remove action defined as an admin method."
+        c1, c2, c3, c4 = self.createSomeComments()
+        action_data = {
+            ACTION_CHECKBOX_NAME: [1],
+            'action' : 'remove',
+            'index' : c1.pk,
+        }
+        response = self.client.post('/admin/comments/comment/', action_data)
+        c = Comment.objects.get(pk=c1.pk)
+        self.assertTrue(c.is_removed)
+        self.assertEqual(c.flags.filter(flag=CommentFlag.MODERATOR_DELETION, user__username="super").count(), 1)
+
+    def test_remove_action_signals(self):
+        "Test signal is received upon remove action."
+        def receive(sender, **kwargs):
+            received_signals.append(kwargs.get('signal'))
+
+        received_signals = []
+        signals.comment_was_flagged.connect(receive)
+
+        self.test_comment_admin_remove_action()
+        self.assertEqual(received_signals, [signals.comment_was_flagged])
+
diff --git a/tests/regressiontests/comment_tests/urls.py b/tests/regressiontests/comment_tests/urls.py
index 0058689..76ca4b9 100644
--- a/tests/regressiontests/comment_tests/urls.py
+++ b/tests/regressiontests/comment_tests/urls.py
@@ -1,4 +1,5 @@
 from django.conf.urls.defaults import *
+from django.contrib import admin
 
 urlpatterns = patterns('regressiontests.comment_tests.custom_comments.views',
     url(r'^post/$',          'custom_submit_comment'),
@@ -7,3 +8,7 @@ urlpatterns = patterns('regressiontests.comment_tests.custom_comments.views',
     url(r'^approve/(\d+)/$', 'custom_approve_comment'),
 )
 
+urlpatterns += patterns('',
+    url(r'^admin/', include(admin.site.urls)),
+)
+
