Skip to content

Commit

Permalink
Merge pull request #4473 from hypothesis/add-nipsa-index-for-moderate…
Browse files Browse the repository at this point in the history
…d-ann

Mark moderated annotations as nipsa'd in search index
  • Loading branch information
chdorner committed Apr 5, 2017
2 parents 7dd19a4 + 1888860 commit c4b2bfc
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 38 deletions.
25 changes: 20 additions & 5 deletions h/nipsa/subscribers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
# -*- coding: utf-8 -*-

from __future__ import unicode_literals


def transform_annotation(event):
"""Add a {"nipsa": True} field on annotations whose users are flagged."""
annotation = event.annotation_dict
nipsa_service = event.request.find_service(name='nipsa')
if 'user' in annotation and nipsa_service.is_flagged(annotation['user']):
annotation['nipsa'] = True
"""Add a {"nipsa": True} field on moderated annotations or those whose users are flagged."""
payload = event.annotation_dict

nipsa = _user_nipsa(event.request, payload)
nipsa = nipsa or _annotation_moderated(event.request, payload)

if nipsa:
payload['nipsa'] = True


def _user_nipsa(request, payload):
nipsa_service = request.find_service(name='nipsa')
return 'user' in payload and nipsa_service.is_flagged(payload['user'])


def _annotation_moderated(request, payload):
svc = request.find_service(name='annotation_moderation')
return svc.hidden(payload['id'])
19 changes: 15 additions & 4 deletions h/services/annotation_moderation.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ class AnnotationModerationService(object):
def __init__(self, session):
self.session = session

def hidden(self, annotation_id):
"""
Check if an annotation id is hidden.
:param annotation_id: The id of the annotation to check.
:type annotation: unicode
:returns: true/false boolean
:rtype: bool
"""
q = self.session.query(models.AnnotationModeration) \
.filter_by(annotation_id=annotation_id)
return self.session.query(q.exists()).scalar()

def hide(self, annotation):
"""
Hide an annotation from other users.
Expand All @@ -23,10 +37,7 @@ def hide(self, annotation):
:type annotation: h.models.Annotation
"""

query = self.session.query(models.AnnotationModeration) \
.filter_by(annotation=annotation)

if query.count() > 0:
if self.hidden(annotation.id):
return

mod = models.AnnotationModeration(annotation=annotation)
Expand Down
5 changes: 5 additions & 0 deletions h/views/api_moderation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pyramid import security
from pyramid.httpexceptions import HTTPNoContent, HTTPNotFound

from h import events
from h.views.api import api_config


Expand All @@ -19,4 +20,8 @@ def create(context, request):

svc = request.find_service(name='annotation_moderation')
svc.hide(context.annotation)

event = events.AnnotationEvent(request, context.annotation.id, 'update')
request.notify_after_commit(event)

return HTTPNoContent()
73 changes: 48 additions & 25 deletions tests/h/nipsa/subscribers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,51 @@
FakeEvent = namedtuple('FakeEvent', ['request', 'annotation_dict'])


@pytest.mark.usefixtures('nipsa_service')
@pytest.mark.parametrize("ann,flagged", [
({"user": "george"}, True),
({"user": "georgia"}, False),
({}, False),
])
def test_transform_annotation(ann, flagged, nipsa_service, pyramid_request):
nipsa_service.is_flagged.return_value = flagged
event = FakeEvent(request=pyramid_request,
annotation_dict=ann)

subscribers.transform_annotation(event)

if flagged:
assert ann["nipsa"] is True
else:
assert "nipsa" not in ann


@pytest.fixture
def nipsa_service(pyramid_config):
service = mock.Mock(spec_set=['is_flagged'])
service.is_flagged.return_value = False
pyramid_config.register_service(service, name='nipsa')
return service
@pytest.mark.usefixtures('nipsa_service', 'moderation_service')
class TestTransformAnnotation(object):
@pytest.mark.parametrize('ann,flagged', [
({'id': 'ann-1', 'user': 'george'}, True),
({'id': 'ann-2', 'user': 'georgia'}, False),
({'id': 'ann-3'}, False),
])
def test_with_user_nipsa(self, ann, flagged, nipsa_service, pyramid_request):
nipsa_service.is_flagged.return_value = flagged
event = FakeEvent(request=pyramid_request,
annotation_dict=ann)

subscribers.transform_annotation(event)

if flagged:
assert ann['nipsa'] is True
else:
assert 'nipsa' not in ann

@pytest.mark.parametrize('ann,moderated', [
({'id': 'normal'}, False),
({'id': 'moderated'}, True)
])
def test_with_moderated_annotation(self, ann, moderated, moderation_service, pyramid_request):
moderation_service.hidden.return_value = moderated
event = FakeEvent(request=pyramid_request,
annotation_dict=ann)

subscribers.transform_annotation(event)

if moderated:
assert ann['nipsa'] is True
else:
assert 'nipsa' not in ann

@pytest.fixture
def nipsa_service(self, pyramid_config):
service = mock.Mock(spec_set=['is_flagged'])
service.is_flagged.return_value = False
pyramid_config.register_service(service, name='nipsa')
return service

@pytest.fixture
def moderation_service(self, pyramid_config):
service = mock.Mock(spec_set=['hidden'])
service.hidden.return_value = False
pyramid_config.register_service(service, name='annotation_moderation')
return service
21 changes: 17 additions & 4 deletions tests/h/services/annotation_moderation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
from h.services.annotation_moderation import annotation_moderation_service_factory


class TestAnnotationModerationServiceHidden(object):
def test_it_returns_true_for_moderated_annotation(self, svc, factories):
mod = factories.AnnotationModeration()

assert svc.hidden(mod.annotation.id) is True

def test_it_returns_false_for_non_moderated_annotation(self, svc, factories):
annotation = factories.Annotation()

assert svc.hidden(annotation.id) is False


class TestAnnotationModerationServiceHide(object):
def test_it_creates_annotation_moderation(self, svc, factories, db_session):
annotation = factories.Annotation()
Expand All @@ -31,10 +43,6 @@ def test_it_skips_creating_moderation_when_already_exists(self, svc, factories,

assert count == 1

@pytest.fixture
def svc(self, db_session):
return AnnotationModerationService(db_session)


class TestAnnotationNipsaServiceFactory(object):
def test_it_returns_service(self, pyramid_request):
Expand All @@ -44,3 +52,8 @@ def test_it_returns_service(self, pyramid_request):
def test_it_provides_request_db_as_session(self, pyramid_request):
svc = annotation_moderation_service_factory(None, pyramid_request)
assert svc.session == pyramid_request.db


@pytest.fixture
def svc(db_session):
return AnnotationModerationService(db_session)
18 changes: 18 additions & 0 deletions tests/h/views/api_moderation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ def test_it_hides_the_annotation(self, pyramid_request, resource, moderation_ser

moderation_service.hide.assert_called_once_with(resource.annotation)

def test_it_publishes_update_event(self, pyramid_request, resource, events):
views.create(resource, pyramid_request)

events.AnnotationEvent.assert_called_once_with(
pyramid_request, resource.annotation.id, 'update')

pyramid_request.notify_after_commit.assert_called_once_with(
events.AnnotationEvent.return_value)

def test_it_renders_no_content(self, pyramid_request, resource):
response = views.create(resource, pyramid_request)
assert isinstance(response, HTTPNoContent)
Expand Down Expand Up @@ -45,3 +54,12 @@ def has_permission(self, pyramid_request):
func = mock.Mock(return_value=True)
pyramid_request.has_permission = func
return func

@pytest.fixture
def events(self, patch):
return patch('h.views.api_moderation.events')

@pytest.fixture
def pyramid_request(self, pyramid_request):
pyramid_request.notify_after_commit = mock.Mock()
return pyramid_request

0 comments on commit c4b2bfc

Please sign in to comment.