Comment changes for federation

This adds a new Comment link table that is used to link between some
object and then the comment object, which can be more or less any
object in Mediagoblin. The MediaComment has been renamed to
TextComment as that more aptly describes what it is. There is
migrations for these changes.

There is also the conslidation of the Report tables into a single
Report table, the same with the Notification objects. This is because
both of them split out MediaEntry and Comment versions into their own
polymorphic versions from a base, this is no longer a meaningful
distinction as comments can be anything.
This commit is contained in:
Jessica Tallon
2015-10-20 12:24:54 +00:00
parent fd703bb4d0
commit 64a456a4e5
26 changed files with 760 additions and 350 deletions

View File

@@ -25,7 +25,7 @@ from webtest import AppError
from .resources import GOOD_JPG
from mediagoblin import mg_globals
from mediagoblin.db.models import User, MediaEntry, MediaComment
from mediagoblin.db.models import User, MediaEntry, TextComment
from mediagoblin.tools.routing import extract_url_arguments
from mediagoblin.tests.tools import fixture_add_user
from mediagoblin.moderation.tools import take_away_privileges
@@ -188,8 +188,7 @@ class TestAPI(object):
# Lets change the image uploader to be self.other_user, this is easier
# than uploading the image as someone else as the way self.mocked_oauth_required
# and self._upload_image.
id = int(data["object"]["id"].split("/")[-2])
media = MediaEntry.query.filter_by(id=id).first()
media = MediaEntry.query.filter_by(public_id=data["object"]["id"]).first()
media.actor = self.other_user.id
media.save()
@@ -232,14 +231,13 @@ class TestAPI(object):
image = json.loads(response.body.decode())["object"]
# Check everything has been set on the media correctly
id = int(image["id"].split("/")[-2])
media = MediaEntry.query.filter_by(id=id).first()
media = MediaEntry.query.filter_by(public_id=image["id"]).first()
assert media.title == title
assert media.description == description
assert media.license == license
# Check we're being given back everything we should on an update
assert int(image["id"].split("/")[-2]) == media.id
assert image["id"] == media.public_id
assert image["displayName"] == title
assert image["content"] == description
assert image["license"] == license
@@ -288,8 +286,7 @@ class TestAPI(object):
request = test_app.get(object_uri)
image = json.loads(request.body.decode())
entry_id = int(image["id"].split("/")[-2])
entry = MediaEntry.query.filter_by(id=entry_id).first()
entry = MediaEntry.query.filter_by(public_id=image["id"]).first()
assert request.status_code == 200
@@ -319,8 +316,7 @@ class TestAPI(object):
assert response.status_code == 200
# Find the objects in the database
media_id = int(data["object"]["id"].split("/")[-2])
media = MediaEntry.query.filter_by(id=media_id).first()
media = MediaEntry.query.filter_by(public_id=data["object"]["id"]).first()
comment = media.get_comments()[0]
# Tests that it matches in the database
@@ -382,8 +378,7 @@ class TestAPI(object):
response, comment_data = self._activity_to_feed(test_app, activity)
# change who uploaded the comment as it's easier than changing
comment_id = int(comment_data["object"]["id"].split("/")[-2])
comment = MediaComment.query.filter_by(id=comment_id).first()
comment = TextComment.query.filter_by(public_id=comment_data["object"]["id"]).first()
comment.actor = self.other_user.id
comment.save()
@@ -510,8 +505,7 @@ class TestAPI(object):
response = self._activity_to_feed(test_app, activity)[1]
# Check the media is no longer in the database
media_id = int(object_id.split("/")[-2])
media = MediaEntry.query.filter_by(id=media_id).first()
media = MediaEntry.query.filter_by(public_id=object_id).first()
assert media is None
@@ -552,8 +546,8 @@ class TestAPI(object):
delete = self._activity_to_feed(test_app, activity)[1]
# Verify the comment no longer exists
comment_id = int(comment["object"]["id"].split("/")[-2])
assert MediaComment.query.filter_by(id=comment_id).first() is None
assert TextComment.query.filter_by(public_id=comment["object"]["id"]).first() is None
comment_id = comment["object"]["id"]
# Check we've got a delete activity back
assert "id" in delete
@@ -593,7 +587,6 @@ class TestAPI(object):
comment = self._activity_to_feed(test_app, activity)[1]
# Verify the comment reflects the changes
comment_id = int(comment["object"]["id"].split("/")[-2])
model = MediaComment.query.filter_by(id=comment_id).first()
model = TextComment.query.filter_by(public_id=comment["object"]["id"]).first()
assert model.content == activity["object"]["content"]

View File

@@ -24,7 +24,7 @@ from mediagoblin.db.base import Session
from mediagoblin.media_types import sniff_media
from mediagoblin.submit.lib import new_upload_entry
from mediagoblin.submit.task import collect_garbage
from mediagoblin.db.models import User, MediaEntry, MediaComment
from mediagoblin.db.models import User, MediaEntry, TextComment, Comment
from mediagoblin.tests.tools import fixture_add_user, fixture_media_entry
@@ -46,25 +46,31 @@ def test_user_deletes_other_comments(test_app):
Session.flush()
# Create all 4 possible comments:
for u_id in (user_a.id, user_b.id):
for m_id in (media_a.id, media_b.id):
cmt = MediaComment()
cmt.media_entry = m_id
cmt.actor = u_id
for u in (user_a, user_b):
for m in (media_a, media_b):
cmt = TextComment()
cmt.actor = u.id
cmt.content = u"Some Comment"
Session.add(cmt)
# think i need this to get the command ID
Session.flush()
link = Comment()
link.target = m
link.comment = cmt
Session.add(link)
Session.flush()
usr_cnt1 = User.query.count()
med_cnt1 = MediaEntry.query.count()
cmt_cnt1 = MediaComment.query.count()
cmt_cnt1 = TextComment.query.count()
User.query.get(user_a.id).delete(commit=False)
usr_cnt2 = User.query.count()
med_cnt2 = MediaEntry.query.count()
cmt_cnt2 = MediaComment.query.count()
cmt_cnt2 = TextComment.query.count()
# One user deleted
assert usr_cnt2 == usr_cnt1 - 1
@@ -77,7 +83,7 @@ def test_user_deletes_other_comments(test_app):
usr_cnt2 = User.query.count()
med_cnt2 = MediaEntry.query.count()
cmt_cnt2 = MediaComment.query.count()
cmt_cnt2 = TextComment.query.count()
# All users gone
assert usr_cnt2 == usr_cnt1 - 2

View File

@@ -18,7 +18,8 @@ import pytest
from mediagoblin.tests.tools import (fixture_add_user,
fixture_add_comment_report, fixture_add_comment)
from mediagoblin.db.models import User, LocalUser, CommentReport, MediaComment, UserBan
from mediagoblin.db.models import User, LocalUser, Report, TextComment, \
UserBan, GenericModelReference
from mediagoblin.tools import template, mail
from webtest import AppError
@@ -102,15 +103,15 @@ class TestModerationViews:
# to a reported comment
#----------------------------------------------------------------------
fixture_add_comment_report(reported_user=self.user)
comment_report = CommentReport.query.filter(
CommentReport.reported_user==self.user).first()
comment_report = Report.query.filter(
Report.reported_user==self.user).first()
response = self.test_app.get('/mod/reports/{0}/'.format(
comment_report.id))
assert response.status == '200 OK'
self.query_for_users()
comment_report = CommentReport.query.filter(
CommentReport.reported_user==self.user).first()
comment_report = Report.query.filter(
Report.reported_user==self.user).first()
response, context = self.do_post({'action_to_resolve':[u'takeaway'],
'take_away_privileges':[u'commenter'],
@@ -118,15 +119,15 @@ class TestModerationViews:
url='/mod/reports/{0}/'.format(comment_report.id))
self.query_for_users()
comment_report = CommentReport.query.filter(
CommentReport.reported_user==self.user).first()
comment_report = Report.query.filter(
Report.reported_user==self.user).first()
assert response.status == '302 FOUND'
assert not self.user.has_privilege(u'commenter')
assert comment_report.is_archived_report() is True
fixture_add_comment_report(reported_user=self.user)
comment_report = CommentReport.query.filter(
CommentReport.reported_user==self.user).first()
comment_report = Report.query.filter(
Report.reported_user==self.user).first()
# Then, test a moderator sending an email to a user in response to a
# reported comment
@@ -139,8 +140,8 @@ class TestModerationViews:
url='/mod/reports/{0}/'.format(comment_report.id))
self.query_for_users()
comment_report = CommentReport.query.filter(
CommentReport.reported_user==self.user).first()
comment_report = Report.query.filter(
Report.reported_user==self.user).first()
assert response.status == '302 FOUND'
assert mail.EMAIL_TEST_MBOX_INBOX == [{'to': [u'regular@example.com'],
'message': 'Content-Type: text/plain; charset="utf-8"\n\
@@ -157,13 +158,17 @@ VGhpcyBpcyB5b3VyIGxhc3Qgd2FybmluZywgcmVndWxhci4uLi4=\n',
self.query_for_users()
fixture_add_comment(author=self.user.id,
comment=u'Comment will be removed')
test_comment = MediaComment.query.filter(
MediaComment.actor==self.user.id).first()
test_comment = TextComment.query.filter(
TextComment.actor==self.user.id).first()
fixture_add_comment_report(comment=test_comment,
reported_user=self.user)
comment_report = CommentReport.query.filter(
CommentReport.comment==test_comment).filter(
CommentReport.resolved==None).first()
comment_gmr = GenericModelReference.query.filter_by(
obj_pk=test_comment.id,
model_type=test_comment.__tablename__
).first()
comment_report = Report.query.filter(
Report.object_id==comment_gmr.id).filter(
Report.resolved==None).first()
response, context = self.do_post(
{'action_to_resolve':[u'userban', u'delete'],
@@ -176,17 +181,17 @@ VGhpcyBpcyB5b3VyIGxhc3Qgd2FybmluZywgcmVndWxhci4uLi4=\n',
test_user_ban = UserBan.query.filter(
UserBan.user_id == self.user.id).first()
assert test_user_ban is not None
test_comment = MediaComment.query.filter(
MediaComment.actor==self.user.id).first()
test_comment = TextComment.query.filter(
TextComment.actor==self.user.id).first()
assert test_comment is None
# Then, test what happens when a moderator attempts to punish an admin
# from a reported comment on an admin.
#----------------------------------------------------------------------
fixture_add_comment_report(reported_user=self.admin_user)
comment_report = CommentReport.query.filter(
CommentReport.reported_user==self.admin_user).filter(
CommentReport.resolved==None).first()
comment_report = Report.query.filter(
Report.reported_user==self.admin_user).filter(
Report.resolved==None).first()
response, context = self.do_post({'action_to_resolve':[u'takeaway'],
'take_away_privileges':[u'active'],

View File

@@ -20,8 +20,7 @@ import six.moves.urllib.parse as urlparse
from mediagoblin.tools import template, mail
from mediagoblin.db.models import Notification, CommentNotification, \
CommentSubscription
from mediagoblin.db.models import Notification, CommentSubscription
from mediagoblin.db.base import Session
from mediagoblin.notifications import mark_comment_notification_seen
@@ -109,11 +108,10 @@ class TestNotifications:
notification = notifications[0]
assert type(notification) == CommentNotification
assert notification.seen == False
assert notification.user_id == user.id
assert notification.subject.get_actor.id == self.test_user.id
assert notification.subject.content == u'Test comment #42'
assert notification.obj().get_actor.id == self.test_user.id
assert notification.obj().content == u'Test comment #42'
if wants_email == True:
assert mail.EMAIL_TEST_MBOX_INBOX == [
@@ -130,7 +128,7 @@ otherperson@example.com\n\nSGkgb3RoZXJwZXJzb24sCmNocmlzIGNvbW1lbnRlZCBvbiB5b3VyI
# Save the ids temporarily because of DetachedInstanceError
notification_id = notification.id
comment_id = notification.subject.id
comment_id = notification.obj().get_comment_link().id
self.logout()
self.login('otherperson', 'nosreprehto')

View File

@@ -20,8 +20,7 @@ import six
from mediagoblin.tools import template
from mediagoblin.tests.tools import (fixture_add_user, fixture_media_entry,
fixture_add_comment, fixture_add_comment_report)
from mediagoblin.db.models import (MediaReport, CommentReport, User, LocalUser,
MediaComment)
from mediagoblin.db.models import Report, User, LocalUser, TextComment
class TestReportFiling:
@@ -80,7 +79,7 @@ class TestReportFiling:
assert response.status == "302 FOUND"
media_report = MediaReport.query.first()
media_report = Report.query.first()
allie_user, natalie_user = self.query_for_users()
assert media_report is not None
@@ -88,7 +87,6 @@ class TestReportFiling:
assert media_report.reporter_id == allie_id
assert media_report.reported_user_id == natalie_user.id
assert media_report.created is not None
assert media_report.discriminator == 'media_report'
def testCommentReports(self):
self.login(u'allie')
@@ -98,9 +96,11 @@ class TestReportFiling:
media_entry = fixture_media_entry(uploader=natalie_user.id,
state=u'processed')
mid = media_entry.id
fixture_add_comment(media_entry=mid,
author=natalie_user.id)
comment = MediaComment.query.first()
fixture_add_comment(
media_entry=media_entry,
author=natalie_user.id
)
comment = TextComment.query.first()
comment_uri_slug = '/u/{0}/m/{1}/c/{2}/'.format(natalie_user.username,
media_entry.slug,
@@ -115,7 +115,7 @@ class TestReportFiling:
assert response.status == "302 FOUND"
comment_report = CommentReport.query.first()
comment_report = Report.query.first()
allie_user, natalie_user = self.query_for_users()
assert comment_report is not None
@@ -123,7 +123,6 @@ class TestReportFiling:
assert comment_report.reporter_id == allie_id
assert comment_report.reported_user_id == natalie_user.id
assert comment_report.created is not None
assert comment_report.discriminator == 'comment_report'
def testArchivingReports(self):
self.login(u'natalie')
@@ -132,14 +131,14 @@ class TestReportFiling:
fixture_add_comment(author=allie_user.id,
comment=u'Comment will be removed')
test_comment = MediaComment.query.filter(
MediaComment.actor==allie_user.id).first()
test_comment = TextComment.query.filter(
TextComment.actor==allie_user.id).first()
fixture_add_comment_report(comment=test_comment,
reported_user=allie_user,
report_content=u'Testing Archived Reports #1',
reporter=natalie_user)
comment_report = CommentReport.query.filter(
CommentReport.reported_user==allie_user).first()
comment_report = Report.query.filter(
Report.reported_user==allie_user).first()
assert comment_report.report_content == u'Testing Archived Reports #1'
response, context = self.do_post(
@@ -151,10 +150,10 @@ class TestReportFiling:
assert response.status == "302 FOUND"
allie_user, natalie_user = self.query_for_users()
archived_report = CommentReport.query.filter(
CommentReport.reported_user==allie_user).first()
archived_report = Report.query.filter(
Report.reported_user==allie_user).first()
assert CommentReport.query.count() != 0
assert Report.query.count() != 0
assert archived_report is not None
assert archived_report.report_content == u'Testing Archived Reports #1'
assert archived_report.reporter_id == natalie_id
@@ -164,4 +163,3 @@ class TestReportFiling:
assert archived_report.result == u'''This is a test of archiving reports.
natalie banned user allie indefinitely.
natalie deleted the comment.'''
assert archived_report.discriminator == 'comment_report'

View File

@@ -99,8 +99,14 @@ class TestSubmission:
return {'upload_files': [('file', filename)]}
def check_comments(self, request, media_id, count):
comments = request.db.MediaComment.query.filter_by(media_entry=media_id)
assert count == len(list(comments))
gmr = request.db.GenericModelReference.query.filter_by(
obj_pk=media_id,
model_type=request.db.MediaEntry.__tablename__
).first()
if gmr is None and count <= 0:
return # Yerp it's fine.
comments = request.db.Comment.query.filter_by(target_id=gmr.id)
assert count == comments.count()
def test_missing_fields(self):
# Test blank form

View File

@@ -25,9 +25,9 @@ from paste.deploy import loadapp
from webtest import TestApp
from mediagoblin import mg_globals
from mediagoblin.db.models import User, LocalUser, MediaEntry, Collection, MediaComment, \
CommentSubscription, CommentNotification, Privilege, CommentReport, Client, \
RequestToken, AccessToken, Activity, Generator
from mediagoblin.db.models import User, LocalUser, MediaEntry, Collection, TextComment, \
CommentSubscription, Notification, Privilege, Report, Client, \
RequestToken, AccessToken, Activity, Generator, Comment
from mediagoblin.tools import testing
from mediagoblin.init.config import read_mediagoblin_config
from mediagoblin.db.base import Session
@@ -222,14 +222,16 @@ def fixture_comment_subscription(entry, notify=True, send_email=None):
return cs
def fixture_add_comment_notification(entry_id, subject_id, user_id,
def fixture_add_comment_notification(entry, subject, user,
seen=False):
cn = CommentNotification(user_id=user_id,
seen=seen,
subject_id=subject_id)
cn = Notification(
user_id=user,
seen=seen,
)
cn.obj = subject
cn.save()
cn = CommentNotification.query.filter_by(id=cn.id).first()
cn = Notification.query.filter_by(id=cn.id).first()
Session.expunge(cn)
@@ -309,22 +311,27 @@ def fixture_add_comment(author=None, media_entry=None, comment=None):
author = fixture_add_user().id
if media_entry is None:
media_entry = fixture_media_entry().id
media_entry = fixture_media_entry()
if comment is None:
comment = \
'Auto-generated test comment by user #{0} on media #{0}'.format(
author, media_entry)
comment = MediaComment(actor=author,
media_entry=media_entry,
content=comment)
text_comment = TextComment(
actor=author,
content=comment
)
text_comment.save()
comment.save()
comment_link = Comment()
comment_link.target = media_entry
comment_link.comment = text_comment
comment_link.save()
Session.expunge(comment)
Session.expunge(comment_link)
return comment
return text_comment
def fixture_add_comment_report(comment=None, reported_user=None,
reporter=None, created=None, report_content=None):
@@ -344,12 +351,13 @@ def fixture_add_comment_report(comment=None, reported_user=None,
report_content = \
'Auto-generated test report'
comment_report = CommentReport(comment=comment,
reported_user = reported_user,
reporter = reporter,
created = created,
report_content=report_content)
comment_report = Report()
comment_report.obj = comment
comment_report.reported_user = reported_user
comment_report.reporter = reporter
comment_report.created = created
comment_report.report_content = report_content
comment_report.obj = comment
comment_report.save()
Session.expunge(comment_report)