Ejemplo n.º 1
0
    def test_it_renders_replies(self, links_service, pyramid_request,
                                search_run, factories, group_service):
        ann = AnnotationResource(factories.Annotation(userid='luke'),
                                 group_service, links_service)
        reply1 = AnnotationResource(
            factories.Annotation(userid='sarah',
                                 references=[ann.annotation.id]),
            group_service, links_service)
        reply2 = AnnotationResource(
            factories.Annotation(userid='sarah',
                                 references=[ann.annotation.id]),
            group_service, links_service)

        search_run.return_value = SearchResult(
            1, [ann.annotation.id],
            [reply1.annotation.id, reply2.annotation.id], {})

        pyramid_request.params = {'_separate_replies': '1'}

        expected = {
            'total':
            1,
            'rows': [presenters.AnnotationJSONPresenter(ann).asdict()],
            'replies': [
                presenters.AnnotationJSONPresenter(reply1).asdict(),
                presenters.AnnotationJSONPresenter(reply2).asdict(),
            ]
        }

        assert views.search(pyramid_request) == expected
Ejemplo n.º 2
0
    def test_link(self, group_service, links_service):
        ann = Mock()
        res = AnnotationResource(ann, group_service, links_service)

        result = res.link('json')

        links_service.get.assert_called_once_with(ann, 'json')
        assert result == links_service.get.return_value
Ejemplo n.º 3
0
 def test_acl_private(self, factories, group_service, links_service):
     ann = factories.Annotation(shared=False, userid='saoirse')
     res = AnnotationResource(ann, group_service, links_service)
     actual = res.__acl__()
     expect = [(security.Allow, 'saoirse', 'read'),
               (security.Allow, 'saoirse', 'admin'),
               (security.Allow, 'saoirse', 'update'),
               (security.Allow, 'saoirse', 'delete'), security.DENY_ALL]
     assert actual == expect
Ejemplo n.º 4
0
 def test_acl_private(self, factories, pyramid_request):
     ann = factories.Annotation(shared=False, userid='saoirse')
     res = AnnotationResource(pyramid_request, ann)
     actual = res.__acl__()
     expect = [(security.Allow, 'saoirse', 'read'),
               (security.Allow, 'saoirse', 'admin'),
               (security.Allow, 'saoirse', 'update'),
               (security.Allow, 'saoirse', 'delete'),
               security.DENY_ALL]
     assert actual == expect
Ejemplo n.º 5
0
    def test_rewrites_rangeselectors_same_element(self, group_service,
                                                  fake_links_service):
        """
        A RangeSelector that starts and ends in the same element should be
        rewritten to an XPathSelector refinedBy a TextPositionSelector, for
        the sake of simplicity.
        """
        annotation = mock.Mock(target_uri='http://example.com')
        annotation.target_selectors = [{
            'type': 'RangeSelector',
            'startContainer': '/div[1]/main[1]/article[1]/div[2]/p[339]',
            'startOffset': 12,
            'endContainer': '/div[1]/main[1]/article[1]/div[2]/p[339]',
            'endOffset': 43,
        }]
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        selectors = AnnotationJSONLDPresenter(resource).target[0]['selector']

        assert selectors == [{
            'type': 'XPathSelector',
            'value': '/div[1]/main[1]/article[1]/div[2]/p[339]',
            'refinedBy': {
                'type': 'TextPositionSelector',
                'start': 12,
                'end': 43,
            }
        }]
Ejemplo n.º 6
0
    def test_acl_shared(self,
                        factories,
                        pyramid_config,
                        pyramid_request,
                        groupid,
                        userid,
                        permitted,
                        group_service,
                        links_service):
        """
        Shared annotation resources should delegate their 'read' permission to
        their containing group.
        """
        # Set up the test with a dummy authn policy and a real ACL authz
        # policy:
        policy = ACLAuthorizationPolicy()
        pyramid_config.testing_securitypolicy(userid)
        pyramid_config.set_authorization_policy(policy)

        ann = factories.Annotation(shared=True,
                                   userid='mioara',
                                   groupid=groupid)
        res = AnnotationResource(ann, group_service, links_service)

        if permitted:
            assert pyramid_request.has_permission('read', res)
        else:
            assert not pyramid_request.has_permission('read', res)
Ejemplo n.º 7
0
def test_og_no_document(render_app_html, pyramid_request, group_service, links_service):
    annotation = Annotation(id='123', userid='foo', target_uri='http://example.com')
    context = AnnotationResource(annotation, group_service, links_service)

    render_app_html.return_value = '<html></html>'
    main.annotation_page(context, pyramid_request)
    args, kwargs = render_app_html.call_args
    test = lambda d: 'foo' in d['content']
    assert any(test(d) for d in kwargs['extra']['meta_attrs'])
Ejemplo n.º 8
0
    def test_id_returns_jsonld_id_link(self, group_service,
                                       fake_links_service):
        annotation = mock.Mock(id='foobar')
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        presenter = AnnotationJSONLDPresenter(resource)

        assert presenter.id == 'http://fake-link/jsonld_id'
Ejemplo n.º 9
0
    def test_asdict_extra_cannot_override_other_data(self, document_asdict,
                                                     group_service,
                                                     fake_links_service):
        ann = mock.Mock(id='the-real-id', extra={'id': 'the-extra-id'})
        resource = AnnotationResource(ann, group_service, fake_links_service)
        document_asdict.return_value = {}

        presented = AnnotationJSONPresenter(resource).asdict()
        assert presented['id'] == 'the-real-id'
Ejemplo n.º 10
0
def test_og_no_document(pyramid_request, group_service, links_service, sidebar_app):
    annotation = Annotation(id='123', userid='foo', target_uri='http://example.com')
    context = AnnotationResource(annotation, group_service, links_service)
    sidebar_app.side_effect = _fake_sidebar_app

    ctx = main.annotation_page(context, pyramid_request)

    def test(d):
        return 'foo' in d['content']
    assert any(test(d) for d in ctx['meta_attrs'])
Ejemplo n.º 11
0
    def test_id_passes_annotation_to_link_service(self, group_service,
                                                  fake_links_service):
        annotation = mock.Mock(id='foobar')
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        presenter = AnnotationJSONLDPresenter(resource)
        _ = presenter.id

        assert fake_links_service.last_annotation == annotation
Ejemplo n.º 12
0
    def test_asdict_merges_formatters(self, group_service, fake_links_service):
        ann = mock.Mock(id='the-real-id', extra={})
        resource = AnnotationResource(ann, group_service, fake_links_service)

        presenter = AnnotationJSONPresenter(resource)
        presenter.add_formatter(FakeFormatter({'flagged': 'nope'}))
        presenter.add_formatter(FakeFormatter({'nipsa': 'maybe'}))
        presented = presenter.asdict()

        assert presented['flagged'] == 'nope'
        assert presented['nipsa'] == 'maybe'
Ejemplo n.º 13
0
    def test_it_renders_search_results(self, links_service, pyramid_request,
                                       search_run, factories, group_service):
        ann1 = AnnotationResource(factories.Annotation(userid='luke'),
                                  group_service, links_service)
        ann2 = AnnotationResource(factories.Annotation(userid='sarah'),
                                  group_service, links_service)

        search_run.return_value = SearchResult(
            2, [ann1.annotation.id, ann2.annotation.id], [], {})

        expected = {
            'total':
            2,
            'rows': [
                presenters.AnnotationJSONPresenter(ann1).asdict(),
                presenters.AnnotationJSONPresenter(ann2).asdict(),
            ]
        }

        assert views.search(pyramid_request) == expected
Ejemplo n.º 14
0
    def test_asdict_extra_uses_copy_of_extra(self, document_asdict,
                                             group_service,
                                             fake_links_service):
        extra = {'foo': 'bar'}
        ann = mock.Mock(id='my-id', extra=extra)
        resource = AnnotationResource(ann, group_service, fake_links_service)
        document_asdict.return_value = {}

        AnnotationJSONPresenter(resource).asdict()

        # Presenting the annotation shouldn't change the "extra" dict.
        assert extra == {'foo': 'bar'}
Ejemplo n.º 15
0
def test_og_document(render_app_html, annotation_document, document_title, pyramid_request, group_service, links_service):
    annotation = Annotation(id='123', userid='foo', target_uri='http://example.com')
    context = AnnotationResource(annotation, group_service, links_service)
    document = Document()
    annotation_document.return_value = document
    document_title.return_value = 'WikiHow — How to Make a ☆Starmap☆'

    render_app_html.return_value = '<html></html>'
    main.annotation_page(context, pyramid_request)
    args, kwargs = render_app_html.call_args
    test = lambda d: 'foo' in d['content'] and 'Starmap' in d['content']
    assert any(test(d) for d in kwargs['extra']['meta_attrs'])
Ejemplo n.º 16
0
    def test_acl_deleted(self, factories, group_service, links_service):
        """
        Nobody -- not even the owner -- should have any permissions on a
        deleted annotation.
        """
        policy = ACLAuthorizationPolicy()

        ann = factories.Annotation(userid='saoirse', deleted=True)
        res = AnnotationResource(ann, group_service, links_service)

        for perm in ['read', 'admin', 'update', 'delete']:
            assert not policy.permits(res, ['saiorse'], perm)
Ejemplo n.º 17
0
def _generate_annotation_event(message, socket, annotation, user_nipsad,
                               group_service):
    """
    Get message about annotation event `message` to be sent to `socket`.

    Inspects the embedded annotation event and decides whether or not the
    passed socket should receive notification of the event.

    Returns None if the socket should not receive any message about this
    annotation event, otherwise a dict containing information about the event.
    """
    action = message['action']

    if action == 'read':
        return None

    if message['src_client_id'] == socket.client_id:
        return None

    # We don't send anything until we have received a filter from the client
    if socket.filter is None:
        return None

    # Don't sent annotations from NIPSA'd users to anyone other than that
    # user.
    if user_nipsad and socket.authenticated_userid != annotation.userid:
        return None

    notification = {
        'type': 'annotation-notification',
        'options': {
            'action': action
        },
    }

    base_url = socket.registry.settings.get('h.app_url',
                                            'http://localhost:5000')
    links_service = LinksService(base_url, socket.registry)
    resource = AnnotationResource(annotation, group_service, links_service)
    serialized = presenters.AnnotationJSONPresenter(resource).asdict()

    permissions = serialized.get('permissions')
    if not _authorized_to_read(socket.effective_principals, permissions):
        return None

    if not socket.filter.match(serialized, action):
        return None

    notification['payload'] = [serialized]
    if action == 'delete':
        notification['payload'] = [{'id': annotation.id}]
    return notification
Ejemplo n.º 18
0
    def test_bodies_returns_textual_body(self, group_service,
                                         fake_links_service):
        annotation = mock.Mock(text='Flib flob flab', tags=None)
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        bodies = AnnotationJSONLDPresenter(resource).bodies

        assert bodies == [{
            'type': 'TextualBody',
            'value': 'Flib flob flab',
            'format': 'text/markdown',
        }]
Ejemplo n.º 19
0
def _present_annotations(request, ids):
    """Load annotations by id from the database and present them."""
    def eager_load_documents(query):
        return query.options(
            subqueryload(models.Annotation.document))

    annotations = storage.fetch_ordered_annotations(request.db, ids,
                                                    query_processor=eager_load_documents)
    group_service = request.find_service(IGroupService)
    links_service = request.find_service(name='links')
    return [AnnotationJSONPresenter(
                AnnotationResource(ann, group_service, links_service)).asdict()
            for ann in annotations]
Ejemplo n.º 20
0
    def test_acl_shared_admin_perms(self, factories, group_service, links_service):
        """
        Shared annotation resources should still only give admin/update/delete
        permissions to the owner.
        """
        policy = ACLAuthorizationPolicy()

        ann = factories.Annotation(shared=False, userid='saoirse')
        res = AnnotationResource(ann, group_service, links_service)

        for perm in ['admin', 'update', 'delete']:
            assert policy.permits(res, ['saoirse'], perm)
            assert not policy.permits(res, ['someoneelse'], perm)
Ejemplo n.º 21
0
def test_og_document(annotation_document, document_title, pyramid_request,
                     group_service, links_service, sidebar_app):
    annotation = Annotation(id='123', userid='foo', target_uri='http://example.com')
    context = AnnotationResource(annotation, group_service, links_service)
    document = Document()
    annotation_document.return_value = document
    document_title.return_value = 'WikiHow — How to Make a ☆Starmap☆'
    sidebar_app.side_effect = _fake_sidebar_app

    ctx = main.annotation_page(context, pyramid_request)

    def test(d):
        return 'foo' in d['content'] and 'Starmap' in d['content']
    assert any(test(d) for d in ctx['meta_attrs'])
Ejemplo n.º 22
0
def create(request):
    """Create an annotation from the POST payload."""
    schema = schemas.CreateAnnotationSchema(request)
    appstruct = schema.validate(_json_payload(request))
    group_service = request.find_service(IGroupService)
    annotation = storage.create_annotation(request, appstruct, group_service)

    _publish_annotation_event(request, annotation, 'create')

    links_service = request.find_service(name='links')
    group_service = request.find_service(IGroupService)
    resource = AnnotationResource(annotation, group_service, links_service)
    presenter = AnnotationJSONPresenter(resource)
    return presenter.asdict()
Ejemplo n.º 23
0
    def test_asdict(self, group_service, fake_links_service):
        annotation = mock.Mock(
            id='foobar',
            created=datetime.datetime(2016, 2, 24, 18, 3, 25, 768),
            updated=datetime.datetime(2016, 2, 29, 10, 24, 5, 564),
            userid='acct:luke',
            target_uri='http://example.com',
            text='It is magical!',
            tags=['magic'],
            target_selectors=[{
                'type': 'TestSelector',
                'test': 'foobar'
            }])
        expected = {
            '@context':
            'http://www.w3.org/ns/anno.jsonld',
            'type':
            'Annotation',
            'id':
            'http://fake-link/jsonld_id',
            'created':
            '2016-02-24T18:03:25.000768+00:00',
            'modified':
            '2016-02-29T10:24:05.000564+00:00',
            'creator':
            'acct:luke',
            'body': [{
                'type': 'TextualBody',
                'format': 'text/markdown',
                'value': 'It is magical!'
            }, {
                'type': 'TextualBody',
                'purpose': 'tagging',
                'value': 'magic'
            }],
            'target': [{
                'source': 'http://example.com',
                'selector': [{
                    'type': 'TestSelector',
                    'test': 'foobar'
                }]
            }]
        }

        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)
        result = AnnotationJSONLDPresenter(resource).asdict()

        assert result == expected
Ejemplo n.º 24
0
Archivo: views.py Proyecto: charblanc/h
def update(context, request):
    """Update the specified annotation with data from the PUT payload."""
    schema = schemas.UpdateAnnotationSchema(request,
                                            context.annotation.target_uri,
                                            context.annotation.groupid)
    appstruct = schema.validate(_json_payload(request))

    annotation = storage.update_annotation(request.db, context.annotation.id,
                                           appstruct)

    _publish_annotation_event(request, annotation, 'update')

    links_service = request.find_service(name='links')
    group_service = request.find_service(IGroupService)
    resource = AnnotationResource(annotation, group_service, links_service)
    presenter = AnnotationJSONPresenter(resource)
    return presenter.asdict()
Ejemplo n.º 25
0
    def test_bodies_appends_tag_bodies(self, group_service,
                                       fake_links_service):
        annotation = mock.Mock(text='Flib flob flab', tags=['giraffe', 'lion'])
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        bodies = AnnotationJSONLDPresenter(resource).bodies

        assert {
            'type': 'TextualBody',
            'value': 'giraffe',
            'purpose': 'tagging',
        } in bodies
        assert {
            'type': 'TextualBody',
            'value': 'lion',
            'purpose': 'tagging',
        } in bodies
Ejemplo n.º 26
0
    def test_permissions(self, annotation, group_readable, action, expected,
                         group_service, fake_links_service):
        annotation.deleted = False

        group_principals = {
            'members':
            (security.Allow, 'group:{}'.format(annotation.groupid), 'read'),
            'world': (security.Allow, security.Everyone, 'read'),
            None:
            security.DENY_ALL,
        }
        group = mock.Mock(spec_set=['__acl__'])
        group.__acl__.return_value = [group_principals[group_readable]]
        group_service.find.return_value = group

        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)
        presenter = AnnotationJSONPresenter(resource)
        assert expected == presenter.permissions[action]
Ejemplo n.º 27
0
    def test_ignores_malformed_rangeselectors(self, group_service,
                                              fake_links_service):
        annotation = mock.Mock(target_uri='http://example.com')
        annotation.target_selectors = [{
            'type':
            'RangeSelector',
            'startContainer':
            '/div[1]/main[1]/article[1]/div[2]/h1[1]',
            'startOffset':
            4,
            'endContainer':
            '/div[1]/main[1]/article[1]/div[2]/p[339]',
        }]
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        target = AnnotationJSONLDPresenter(resource).target[0]

        assert 'selector' not in target
Ejemplo n.º 28
0
def update(context, request):
    """Update the specified annotation with data from the PATCH payload."""
    if request.method == 'PUT' and hasattr(request, 'stats'):
        request.stats.incr('memex.api.deprecated.put_update_annotation')

    schema = schemas.UpdateAnnotationSchema(request,
                                            context.annotation.target_uri,
                                            context.annotation.groupid)
    appstruct = schema.validate(_json_payload(request))

    annotation = storage.update_annotation(request.db, context.annotation.id,
                                           appstruct)

    _publish_annotation_event(request, annotation, 'update')

    links_service = request.find_service(name='links')
    group_service = request.find_service(IGroupService)
    resource = AnnotationResource(annotation, group_service, links_service)
    presenter = AnnotationJSONPresenter(resource)
    return presenter.asdict()
Ejemplo n.º 29
0
    def test_rewrites_rangeselectors_different_element(self, group_service,
                                                       fake_links_service):
        """
        A RangeSelector that starts and ends in the different elements should
        be rewritten to a RangeSelector bounded by two XPathSelectors, each of
        which is refinedBy a "point"-like TextPositionSelector.
        """
        annotation = mock.Mock(target_uri='http://example.com')
        annotation.target_selectors = [{
            'type': 'RangeSelector',
            'startContainer': '/div[1]/main[1]/article[1]/div[2]/h1[1]',
            'startOffset': 4,
            'endContainer': '/div[1]/main[1]/article[1]/div[2]/p[339]',
            'endOffset': 72,
        }]
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        selectors = AnnotationJSONLDPresenter(resource).target[0]['selector']

        assert selectors == [{
            'type': 'RangeSelector',
            'startSelector': {
                'type': 'XPathSelector',
                'value': '/div[1]/main[1]/article[1]/div[2]/h1[1]',
                'refinedBy': {
                    'type': 'TextPositionSelector',
                    'start': 4,
                    'end': 4,
                }
            },
            'endSelector': {
                'type': 'XPathSelector',
                'value': '/div[1]/main[1]/article[1]/div[2]/p[339]',
                'refinedBy': {
                    'type': 'TextPositionSelector',
                    'start': 72,
                    'end': 72,
                }
            },
        }]
Ejemplo n.º 30
0
    def test_ignores_selectors_lacking_types(self, group_service,
                                             fake_links_service):
        annotation = mock.Mock(target_uri='http://example.com')
        annotation.target_selectors = [
            {
                'type': 'TestSelector',
                'test': 'foobar'
            },
            {
                'something': 'else'
            },
        ]
        resource = AnnotationResource(annotation, group_service,
                                      fake_links_service)

        selectors = AnnotationJSONLDPresenter(resource).target[0]['selector']

        assert selectors == [{
            'type': 'TestSelector',
            'test': 'foobar',
        }]
Ejemplo n.º 31
0
    def test_asdict(self, document_asdict, group_service, fake_links_service):
        ann = mock.Mock(id='the-id',
                        created=datetime.datetime(2016, 2, 24, 18, 3, 25, 768),
                        updated=datetime.datetime(2016, 2, 29, 10, 24, 5, 564),
                        userid='acct:luke',
                        target_uri='http://example.com',
                        text='It is magical!',
                        tags=['magic'],
                        groupid='__world__',
                        shared=True,
                        target_selectors=[{
                            'TestSelector': 'foobar'
                        }],
                        references=['referenced-id-1', 'referenced-id-2'],
                        extra={
                            'extra-1': 'foo',
                            'extra-2': 'bar'
                        })
        resource = AnnotationResource(ann, group_service, fake_links_service)

        document_asdict.return_value = {'foo': 'bar'}

        expected = {
            'id':
            'the-id',
            'created':
            '2016-02-24T18:03:25.000768+00:00',
            'updated':
            '2016-02-29T10:24:05.000564+00:00',
            'user':
            '******',
            'uri':
            'http://example.com',
            'text':
            'It is magical!',
            'tags': ['magic'],
            'group':
            '__world__',
            'permissions': {
                'read': ['group:__world__'],
                'admin': ['acct:luke'],
                'update': ['acct:luke'],
                'delete': ['acct:luke']
            },
            'target': [{
                'source': 'http://example.com',
                'selector': [{
                    'TestSelector': 'foobar'
                }]
            }],
            'document': {
                'foo': 'bar'
            },
            'links': {
                'giraffe': 'http://giraffe.com',
                'toad': 'http://toad.net'
            },
            'references': ['referenced-id-1', 'referenced-id-2'],
            'extra-1':
            'foo',
            'extra-2':
            'bar'
        }

        result = AnnotationJSONPresenter(resource).asdict()

        assert result == expected