Ejemplo n.º 1
0
 def test_deny_system_role(self):
     annotation = models.Annotation()
     annotation['permissions'] = {
         'read': [security.Everyone],
     }
     with raises(ValueError):
         annotation.__acl__()
Ejemplo n.º 2
0
 def event(self, action):
     return mock.Mock(
         spec=events.AnnotationEvent(testing.DummyRequest(),
                                     mock.Mock(spec=models.Annotation()),
                                     action),
         action=action,
     )
Ejemplo n.º 3
0
def search(request_params, user=None, search_normalized_uris=False):
    """
    Search with the given params and return the matching annotations.

    :param request_params: the HTTP request params that were posted to the
        h search API
    :type request_params: webob.multidict.NestedMultiDict

    :param user: the authorized user, or None
    :type user: h.accounts.models.User or None

    :param search_normalized_uris: Whether or not to use the "uri" param to
        search against pre-normalized URI fields.
    :type search_normalized_uris: bool

    :returns: a dict with keys "rows" (the list of matching annotations, as
        dicts) and "total" (the number of matching annotations, an int)
    :rtype: dict
    """
    userid = user.id if user else None
    log.debug("Searching with user=%s, for uri=%s", str(userid),
              request_params.get('uri'))

    body = query.build(request_params,
                       userid=userid,
                       search_normalized_uris=search_normalized_uris)
    results = models.Annotation.search_raw(body, user=user, raw_result=True)

    total = results['hits']['total']
    docs = results['hits']['hits']
    rows = [models.Annotation(d['_source'], id=d['_id']) for d in docs]

    return {"rows": rows, "total": total}
Ejemplo n.º 4
0
def search(request_params, user=None):
    """Search with the given params and return the matching annotations.

    :param request_params: the HTTP request params that were posted to the
        h search API
    :type request_params: webob.multidict.NestedMultiDict

    :param user: the authorized user, or None
    :type user: h.accounts.models.User or None

    :returns: a dict with keys "rows" (the list of matching annotations, as
        dicts) and "total" (the number of matching annotations, an int)
    :rtype: dict

    """
    log.debug("Searching with user=%s, for uri=%s",
              user.id if user else 'None', request_params.get('uri'))

    query = build_query(request_params)
    results = models.Annotation.search_raw(query, user=user, raw_result=True)

    total = results['hits']['total']
    docs = results['hits']['hits']
    rows = [models.Annotation(d['_source'], id=d['_id']) for d in docs]

    return {"rows": rows, "total": total}
Ejemplo n.º 5
0
 def test_group_authenticated(self):
     annotation = models.Annotation()
     annotation['permissions'] = {
         'read': ['group:__authenticated__'],
     }
     actual = annotation.__acl__()
     expect = [(security.Allow, security.Authenticated, 'read')]
     assert actual == expect
Ejemplo n.º 6
0
 def test_group_world(self):
     annotation = models.Annotation()
     annotation['permissions'] = {
         'read': ['group:__world__'],
     }
     actual = annotation.__acl__()
     expect = [(security.Allow, security.Everyone, 'read')]
     assert actual == expect
Ejemplo n.º 7
0
 def test_group(self):
     annotation = models.Annotation()
     annotation['permissions'] = {
         'read': ['group:lulapalooza'],
     }
     actual = annotation.__acl__()
     expect = [(security.Allow, 'group:lulapalooza', 'read')]
     assert actual == expect
Ejemplo n.º 8
0
 def test_principal(self):
     annotation = models.Annotation()
     annotation['permissions'] = {
         'read': ['saoirse'],
     }
     actual = annotation.__acl__()
     expect = [(security.Allow, 'saoirse', 'read')]
     assert actual == expect
Ejemplo n.º 9
0
def create_annotation(request, data):
    """
    Create an annotation from passed data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: a dictionary of annotation properties
    :type data: dict

    :returns: the created annotation
    :rtype: dict
    """
    document_uri_dicts = data['document']['document_uri_dicts']
    document_meta_dicts = data['document']['document_meta_dicts']
    del data['document']

    # Replies must have the same group as their parent.
    if data['references']:
        top_level_annotation_id = data['references'][0]
        top_level_annotation = fetch_annotation(request.db,
                                                top_level_annotation_id)
        if top_level_annotation:
            data['groupid'] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                'references.0: ' + _('Annotation {id} does not exist').format(
                    id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in.
    if data['groupid'] != '__world__':
        group_principal = 'group:{}'.format(data['groupid'])
        if group_principal not in request.effective_principals:
            raise schemas.ValidationError('group: ' +
                                          _('You may not create annotations '
                                            'in groups you are not a member '
                                            'of!'))

    annotation = models.Annotation(**data)
    request.db.add(annotation)

    # We need to flush the db here so that annotation.created and
    # annotation.updated get created.
    request.db.flush()

    models.update_document_metadata(request.db, annotation,
                                    document_meta_dicts, document_uri_dicts)

    return annotation
Ejemplo n.º 10
0
def create_annotation(request, data):
    """
    Create an annotation from passed data.

    :param request: the request object
    :type request: pyramid.request.Request

    :param data: a dictionary of annotation properties
    :type data: dict

    :returns: the created annotation
    :rtype: dict
    """
    document_uri_dicts = data['document']['document_uri_dicts']
    document_meta_dicts = data['document']['document_meta_dicts']
    del data['document']

    # Replies must have the same group as their parent.
    if data['references']:
        top_level_annotation_id = data['references'][0]
        top_level_annotation = fetch_annotation(request,
                                                top_level_annotation_id,
                                                _postgres=True)
        if top_level_annotation:
            data['groupid'] = top_level_annotation.groupid
        else:
            raise schemas.ValidationError(
                'references.0: ' +
                _('Annotation {annotation_id} does not exist').format(
                    annotation_id=top_level_annotation_id))

    # The user must have permission to create an annotation in the group
    # they've asked to create one in.
    if data['groupid'] != '__world__':
        group_principal = 'group:{}'.format(data['groupid'])
        if group_principal not in request.effective_principals:
            raise schemas.ValidationError('group: ' +
                                          _('You may not create annotations '
                                            'in groups you are not a member '
                                            'of!'))

    annotation = models.Annotation(**data)
    request.db.add(annotation)

    # We need to flush the db here so that annotation.created and
    # annotation.updated get created.
    request.db.flush()

    documents = models.Document.find_or_create_by_uris(
        request.db,
        annotation.target_uri, [u['uri'] for u in document_uri_dicts],
        created=annotation.created,
        updated=annotation.updated)

    if documents.count() > 1:
        document = models.merge_documents(request.db,
                                          documents,
                                          updated=annotation.updated)
    else:
        document = documents.first()

    document.updated = annotation.updated

    for document_uri_dict in document_uri_dicts:
        models.create_or_update_document_uri(session=request.db,
                                             document=document,
                                             created=annotation.created,
                                             updated=annotation.updated,
                                             **document_uri_dict)

    for document_meta_dict in document_meta_dicts:
        models.create_or_update_document_meta(session=request.db,
                                              document=document,
                                              created=annotation.created,
                                              updated=annotation.updated,
                                              **document_meta_dict)

    return annotation
Ejemplo n.º 11
0
def test_uri_with_no_uri():
    assert models.Annotation().uri == ""
Ejemplo n.º 12
0
Archivo: core.py Proyecto: openbizgit/h
def search(request, params, private=True, separate_replies=False):
    """
    Search with the given params and return the matching annotations.

    :param request: the request object
    :type request: pyramid.request.Request

    :param params: the search parameters
    :type params: dict-like

    :param private: whether or not to include private annotations in the search
        results
    :type private: bool

    :param separate_replies: Whether or not to include a "replies" key in the
        result containing a list of all replies to the annotations in the
        "rows" key. If this is True then the "rows" key will include only
        top-level annotations, not replies.
    :type private: bool

    :returns: A dict with keys:
      "rows" (the list of matching annotations, as dicts)
      "total" (the number of matching annotations, an int)
      "replies": (the list of all replies to the annotations in "rows", if
        separate_replies=True was passed)
    :rtype: dict
    """
    def make_builder():
        builder = query.Builder()
        builder.append_filter(query.AuthFilter(request, private=private))
        builder.append_filter(query.UriFilter())
        builder.append_filter(
            lambda _: nipsa.nipsa_filter(request.authenticated_userid))
        builder.append_filter(query.GroupFilter())
        builder.append_matcher(query.AnyMatcher())
        builder.append_matcher(query.TagsMatcher())
        return builder

    builder = make_builder()
    if separate_replies:
        builder.append_filter(query.TopLevelAnnotationsFilter())
    results = models.Annotation.search_raw(builder.build(params),
                                           raw_result=True,
                                           authorization_enabled=False)

    total = results['hits']['total']
    docs = results['hits']['hits']
    rows = [models.Annotation(d['_source'], id=d['_id']) for d in docs]
    return_value = {"rows": rows, "total": total}

    if separate_replies:
        # Do a second query for all replies to the annotations from the first
        # query.
        builder = make_builder()
        builder.append_matcher(
            query.RepliesMatcher([h['_id'] for h in results['hits']['hits']]))
        reply_results = models.Annotation.search_raw(
            builder.build({'limit': 100}),
            raw_result=True,
            authorization_enabled=False)

        if len(reply_results['hits']['hits']) < reply_results['hits']['total']:
            log.warn("The number of reply annotations exceeded the page size "
                     "of the Elasticsearch query. We currently don't handle "
                     "this, our search API doesn't support pagination of the "
                     "reply set.")

        reply_docs = reply_results['hits']['hits']
        reply_rows = [
            models.Annotation(d['_source'], id=d['_id']) for d in reply_docs
        ]

        return_value["replies"] = reply_rows

    return return_value
Ejemplo n.º 13
0
 def test_admin_party(self):
     annotation = models.Annotation()
     actual = annotation.__acl__()
     expect = [(security.Allow, security.Everyone, security.ALL_PERMISSIONS)
               ]
     assert actual == expect
Ejemplo n.º 14
0
def test_parent_fetches_thread_parent(fetch):
    annotation = models.Annotation(references=['abc123', 'def456'])
    annotation.parent
    fetch.assert_called_with('def456')
Ejemplo n.º 15
0
 def model(self):
     if 'id' in self:
         instance = models.Annotation.fetch(self['id'])
         return instance or models.Annotation(id=self['id'])
     else:
         return models.Annotation()
Ejemplo n.º 16
0
def test_parent_returns_none_if_empty_references():
    annotation = models.Annotation(references=[])
    assert annotation.parent is None
Ejemplo n.º 17
0
def test_parent_returns_none_if_references_not_list():
    annotation = models.Annotation(references={'foo': 'bar'})
    assert annotation.parent is None
Ejemplo n.º 18
0
def test_target_links_from_annotation():
    annotation = models.Annotation(target=[{'source': 'target link'}])
    assert annotation.target_links == ['target link']
Ejemplo n.º 19
0
def test_uri_when_uri_is_not_a_string():
    for uri in (True, None, 23, 23.7, {"foo": False}, [1, 2, 3]):
        assert isinstance(models.Annotation(uri=uri).uri, unicode)
Ejemplo n.º 20
0
 def event(self):
     return mock.Mock(
         spec=AnnotationEvent(testing.DummyRequest(),
                              mock.Mock(spec=models.Annotation()),
                              'create'),
     )
Ejemplo n.º 21
0
def test_uri():
    assert models.Annotation(uri="http://foo.com").uri == "http://foo.com"
Ejemplo n.º 22
0
def test_parent_returns_thread_parent(fetch):
    annotation = models.Annotation(references=['abc123', 'def456'])
    parent = annotation.parent
    assert parent == fetch.return_value