Beispiel #1
0
    def test_it_fetches_and_returns_the_annotation(self, db_session):
        annotation = Annotation(userid='luke')
        db_session.add(annotation)
        db_session.flush()

        actual = storage.fetch_annotation(db_session, annotation.id)
        assert annotation == actual
Beispiel #2
0
    def test_it_fetches_and_returns_the_annotation(self, db_session):
        annotation = Annotation(userid='luke')
        db_session.add(annotation)
        db_session.flush()

        actual = storage.fetch_annotation(db_session, annotation.id)
        assert annotation == actual
Beispiel #3
0
    def __getitem__(self, id):
        annotation = storage.fetch_annotation(self.request.db, id)
        if annotation is None:
            raise KeyError()

        group_service = self.request.find_service(IGroupService)
        links_service = self.request.find_service(name='links')
        return AnnotationResource(annotation, group_service, links_service)
Beispiel #4
0
def add_annotation(id_):
    annotation = storage.fetch_annotation(celery.request.db, id_)
    if annotation:
        index(celery.request.es, annotation, celery.request)

        # If a reindex is running at the moment, add annotation to the new index
        # as well.
        future_index = _current_reindex_new_name(celery.request)
        if future_index is not None:
            index(celery.request.es, annotation, celery.request,
                  target_index=future_index)
Beispiel #5
0
def add_annotation(id_):
    annotation = storage.fetch_annotation(celery.request.db, id_)
    if annotation:
        index(celery.request.es, annotation, celery.request)

        # If a reindex is running at the moment, add annotation to the new index
        # as well.
        future_index = _current_reindex_new_name(celery.request)
        if future_index is not None:
            index(celery.request.es,
                  annotation,
                  celery.request,
                  target_index=future_index)
Beispiel #6
0
def send_reply_notifications(event,
                             get_notification=reply.get_notification,
                             generate_mail=emails.reply_notification.generate,
                             send=mailer.send.delay):
    """Queue any reply notification emails triggered by an annotation event."""
    request = event.request
    with request.tm:
        annotation = storage.fetch_annotation(event.request.db,
                                              event.annotation_id)
        notification = get_notification(request, annotation, event.action)
        if notification is None:
            return
        send_params = generate_mail(request, notification)
        send(*send_params)
Beispiel #7
0
def handle_annotation_event(message, sockets, session):
    id_ = message['annotation_id']
    annotation = storage.fetch_annotation(session, id_)

    if annotation is None:
        log.warn('received annotation event for missing annotation: %s', id_)
        return

    nipsa_service = NipsaService(session)
    user_nipsad = nipsa_service.is_flagged(annotation.userid)

    for socket in sockets:
        reply = _generate_annotation_event(message, socket, annotation, user_nipsad)
        if reply is None:
            continue
        socket.send_json(reply)
Beispiel #8
0
def handle_annotation_event(message, sockets, settings, session):
    id_ = message['annotation_id']
    annotation = storage.fetch_annotation(session, id_)

    if annotation is None:
        log.warn('received annotation event for missing annotation: %s', id_)
        return

    nipsa_service = NipsaService(session)
    user_nipsad = nipsa_service.is_flagged(annotation.userid)

    auth_domain = text_type(settings.get('h.auth_domain', 'localhost'))
    group_service = GroupfinderService(session, auth_domain)

    for socket in sockets:
        reply = _generate_annotation_event(message, socket, annotation,
                                           user_nipsad, group_service)
        if reply is None:
            continue
        socket.send_json(reply)
Beispiel #9
0
def handle_annotation_event(message, sockets, session):
    id_ = message['annotation_id']
    annotation = storage.fetch_annotation(session, id_)

    # FIXME: It isn't really nice to try and get the userid from the fetched
    # annotation or otherwise get it from the maybe-already serialized
    # annotation dict, to then only access the database for the nipsa flag once.
    # We do this because the event action is `delete` at which point we can't
    # load the annotation from the database. Handling annotation deletions is
    # a known problem and will be fixed in the future.
    userid = None
    if annotation:
        userid = annotation.userid
    else:
        userid = message.get('annotation_dict', {}).get('userid')
    nipsa_service = NipsaService(session)
    user_nipsad = nipsa_service.is_flagged(userid)

    for socket in sockets:
        reply = _generate_annotation_event(message, socket, annotation, user_nipsad)
        if reply is None:
            continue
        socket.send_json(reply)
Beispiel #10
0
def send_reply_notifications(event,
                             get_notification=reply.get_notification,
                             generate_mail=emails.reply_notification.generate,
                             send=mailer.send.delay):
    """Queue any reply notification emails triggered by an annotation event."""
    request = event.request
    annotation = storage.fetch_annotation(event.request.db, event.annotation_id)
    action = event.action
    try:
        notification = get_notification(request, annotation, action)
        if notification is None:
            return
        send_params = generate_mail(request, notification)
        send(*send_params)
    # We don't want any exceptions thrown by this code to cause the annotation
    # CRUD action to fail, but we do want to collect the error in Sentry, so we
    # explicitly wrap this here.
    #
    # FIXME: Fix the underlying bugs and remove this try/except.
    except Exception:
        event.request.sentry.captureException()
        if event.request.debug:
            raise
Beispiel #11
0
def send_reply_notifications(event,
                             get_notification=reply.get_notification,
                             generate_mail=emails.reply_notification.generate,
                             send=mailer.send.delay):
    """Queue any reply notification emails triggered by an annotation event."""
    request = event.request
    annotation = storage.fetch_annotation(event.request.db,
                                          event.annotation_id)
    action = event.action
    try:
        notification = get_notification(request, annotation, action)
        if notification is None:
            return
        send_params = generate_mail(request, notification)
        send(*send_params)
    # We don't want any exceptions thrown by this code to cause the annotation
    # CRUD action to fail, but we do want to collect the error in Sentry, so we
    # explicitly wrap this here.
    #
    # FIXME: Fix the underlying bugs and remove this try/except.
    except Exception:
        event.request.sentry.captureException()
        if event.request.debug:
            raise
Beispiel #12
0
 def __getitem__(self, id):
     annotation = storage.fetch_annotation(self.request.db, id)
     if annotation is None:
         raise KeyError()
     return annotation
Beispiel #13
0
def add_annotation(id_):
    annotation = storage.fetch_annotation(celery.request.db, id_)
    if annotation:
        index(celery.request.es, annotation, celery.request)
Beispiel #14
0
def get_notification(request, annotation, action):
    """
    Check if the passed annotation and action pair should send a notification.

    Checks to see if the annotation event represented by the passed annotation
    and action should trigger a notification. If it should, this function
    returns the relevant :py:class:`~h.notification.reply.Notification` object.
    Otherwise, it returns None.

    :param request: the current request object
    :type request: pyramid.request.Request
    :param annotation: the reply annotation
    :type annotation: memex.models.elastic.Annotation or h.models.Annotation
    :param action: the event action
    :type action: str

    :returns: a :py:class:`~h.notification.reply.Notification`, or None
    """
    # Only send notifications when new annotations are created
    if action != 'create':
        return

    # If the annotation doesn't have a parent, or we can't find its parent,
    # then we can't send a notification email.
    parent_id = annotation.parent_id
    if parent_id is None:
        return

    # Now we know we're dealing with a reply
    reply = annotation

    parent = storage.fetch_annotation(request.db, parent_id)
    if parent is None:
        return

    user_service = request.find_service(name='user')

    # If the parent user doesn't exist (anymore), we can't send an email.
    parent_user = user_service.fetch(parent.userid)
    if parent_user is None:
        return

    # If the reply user doesn't exist (anymore), we can't send an email, but
    # this would be super weird, so log a warning.
    reply_user = user_service.fetch(reply.userid)
    if reply_user is None:
        log.warn('user who just replied no longer exists: %s', reply.userid)
        return

    # Do not notify users about their own replies
    if parent_user == reply_user:
        return

    # Don't send reply notifications to the author of the parent annotation if
    # the reply was private.
    if not reply.shared:
        return

    # FIXME: we should be retrieving the document from the root annotation, not
    # the reply, and dealing with the possibility that we have no document
    # metadata.
    if reply.document is None:
        return

    # Bail if there is no active 'reply' subscription for the user being
    # replied to.
    sub = request.db.query(Subscriptions).filter_by(active=True,
                                                    type='reply',
                                                    uri=parent.userid).first()
    if sub is None:
        return

    return Notification(reply, reply_user, parent, parent_user, reply.document)
Beispiel #15
0
 def test_it_does_not_crash_if_id_is_invalid(self, db_session):
     assert storage.fetch_annotation(db_session, 'foo') is None
Beispiel #16
0
    def test_it_fetches_and_returns_the_annotation(self, db_session, factories):
        annotation = factories.Annotation()

        actual = storage.fetch_annotation(db_session, annotation.id)
        assert annotation == actual
Beispiel #17
0
 def test_it_does_not_crash_if_id_is_invalid(self, db_session):
     assert storage.fetch_annotation(db_session, 'foo') is None
Beispiel #18
0
    def test_it_fetches_and_returns_the_annotation(self, db_session,
                                                   factories):
        annotation = factories.Annotation()

        actual = storage.fetch_annotation(db_session, annotation.id)
        assert annotation == actual
Beispiel #19
0
def add_annotation(id_):
    annotation = storage.fetch_annotation(celery.request.db, id_)
    if annotation:
        index(celery.request.es, annotation, celery.request)