예제 #1
0
 def update_notifications(self):
     notifications = [
         ntf.as_dict() for ntf in InAppNotification.objects(
             owner=self.auth_context.org,
             dismissed_by__ne=self.auth_context.user.id)
     ]
     log.info("Emitting notifications list")
     self.send('notifications', notifications)
예제 #2
0
def add_notification_override(request):
    """
    Tags: notifications
    ---
    Add a notification override with the specified properties
    ---
    notification:
      in: path
      type: string
      required: true
    """
    auth_context = auth_context_from_request(request)
    params = params_from_request(request)
    ntf_id = params.get("notification_id")
    if not ntf_id:
        raise RequiredParameterMissingError("notification_id")
    try:
        ntf = Notification.objects.get(id=ntf_id, owner=auth_context.owner)
        ntf.channel.dismiss(auth_context.user)
    except Notification.DoesNotExist:
        raise NotFoundError()
    try:
        np = UserNotificationPolicy.objects.get(owner=auth_context.owner,
                                                user_id=auth_context.user.id)
    except UserNotificationPolicy.DoesNotExist:
        np = UserNotificationPolicy(owner=auth_context.owner,
                                    user_id=auth_context.user.id)
    if not np.has_overriden(ntf):
        override = NotificationOverride()
        override.rid = ntf.rid
        override.rtype = ntf.rtype
        override.channel = ntf.channel.ctype
        np.overrides.append(override)
        np.save()
        # Dismiss relevant notifications in order to not show up again.
        InAppNotification.objects(
            owner=auth_context.owner,
            rid=ntf.rid,
            rtype=ntf.rtype,
            dismissed_by__ne=auth_context.user.id).update(
                push__dismissed_by=auth_context.user.id)
    return Response('OK', 200)
예제 #3
0
    def _modify_and_notify(self, notification, modifier):
        user = notification.user

        old_notifications = [
            json.loads(obj.to_json())
            for obj in InAppNotification.objects(user=user, dismissed=False)
        ]
        modifier(notification)
        new_notifications = [
            json.loads(obj.to_json())
            for obj in InAppNotification.objects(user=user, dismissed=False)
        ]
        patch = jsonpatch.JsonPatch.from_diff(old_notifications,
                                              new_notifications).patch
        if patch:
            data = json.dumps({
                "user": user.id,
                "patch": patch
            },
                              cls=NotificationsEncoder)
            amqp_publish_user(notification.organization,
                              routing_key='patch_notifications',
                              data=data)
예제 #4
0
 def modify(notification):
     if notification.unique:
         similar = InAppNotification.objects(
             user=notification.user,
             organization=notification.organization,
             machine=notification.machine,
             tag=notification.tag,
             cloud=notification.cloud,
             model_id=notification.model_id)
         if similar:
             # unfortunately, queryset does not support pop()
             first = similar[0]
             first.update_from(notification)
             first.save()
             for item in [item for item in similar if item != first]:
                 item.dismissed = True
                 item.save()
         else:
             notification.save()
     else:
         notification.save()
예제 #5
0
    def send(self, users=None, dismiss=False):
        # FIXME Imported here due to circular dependency issues.
        from mist.api.notifications.models import InAppNotification
        from mist.api.notifications.models import UserNotificationPolicy

        # Get the list of `InAppNotifications`s in the current context before
        # any update takes place.
        owner_old_ntfs = list(InAppNotification.objects(owner=self.ntf.owner))

        if not users:
            users = self.ntf.owner.members
        elif not isinstance(users, list):
            users = [users]

        # Save/update/dismiss notifications.
        if dismiss:
            dismissed_by = set(self.ntf.dismissed_by)
            old_dismissed_by = list(dismissed_by)
            dismissed_by |= set(user.id for user in users)
            self.ntf.dismissed_by = list(dismissed_by)

        # Is anyone listening?
        if not amqp_owner_listening(self.ntf.owner.id):
            return

        # Initialize AMQP connection to reuse for multiple messages.
        amqp_conn = Connection(config.AMQP_URI)

        # Re-fetch all notifications in order to calculate the diff between
        # the two lists.
        owner_new_ntfs = list(InAppNotification.objects(owner=self.ntf.owner))

        # Apply each user's notification policy on the above lists to get rid
        # of notifications users are not interested in.
        for user in users:
            user_old_ntfs, user_new_ntfs = [], []
            try:
                np = UserNotificationPolicy.objects.get(user_id=user.id)
            except UserNotificationPolicy.DoesNotExist:
                log.debug('No UserNotificationPolicy found for %s', user)
                user_old_ntfs = [
                    ntf.as_dict() for ntf in owner_old_ntfs if not (
                        self.ntf.id == ntf.id and user.id in old_dismissed_by)
                ]
                user_new_ntfs = [
                    ntf.as_dict() for ntf in owner_new_ntfs
                    if not (self.ntf.id == ntf.id and user.id in dismissed_by)
                ]
            else:
                user_old_ntfs = [
                    ntf.as_dict() for ntf in owner_old_ntfs
                    if not np.has_blocked(ntf) and not (
                        self.ntf.id == ntf.id and user.id in old_dismissed_by)
                ]
                user_new_ntfs = [
                    ntf.as_dict() for ntf in owner_new_ntfs
                    if not np.has_blocked(ntf)
                    and not (self.ntf.id == ntf.id and user.id in dismissed_by)
                ]
            # Now we can save the dismissed notification
            self.ntf.save()

            # Calculate diff.
            patch = jsonpatch.JsonPatch.from_diff(user_old_ntfs,
                                                  user_new_ntfs).patch

            if patch:
                amqp_publish_user(self.ntf.owner.id,
                                  routing_key='patch_notifications',
                                  connection=amqp_conn,
                                  data={
                                      'user': user.id,
                                      'patch': patch
                                  })

        # Finally, try to close the AMQP connection.
        try:
            amqp_conn.close()
        except Exception as exc:
            log.exception(repr(exc))
예제 #6
0
def migrate_notifications(collection):
    """Migrate all non-dismissed in-app notifications"""
    total = collection.find().count()
    failed = 0
    migrated = 0

    print
    print 'Will migrate %d notifications' % total
    print

    for old_ntf in collection.find({
            'dismissed': False,
            'migrated': {
                '$exists': False
            }
    }):
        try:
            print 'Migrating', old_ntf['_id'],
            try:
                owner = Organization.objects.get(id=old_ntf['organization'])
            except Exception:
                print '[ERROR]'
                failed += 1
                traceback.print_exc()
                continue
            ntf = InAppNotification()
            ntf.owner = owner
            ntf.subject = old_ntf['summary']
            ntf.text_body = old_ntf['body']
            ntf.html_body = old_ntf['html_body']
            ntf.rid = old_ntf['machine']['_ref'].id
            ntf.rtype = 'machine'
            ntf.created_at = old_ntf['created_date']
            ntf.save()
        except Exception:
            print '[ERROR]'
            failed += 1
            traceback.print_exc()
        else:
            try:
                collection.update_one({'_id': old_ntf['_id']},
                                      {'$set': {
                                          'migrated': True
                                      }})
            except Exception:
                print '[ERROR]'
                failed += 1
                traceback.print_exc()
                try:
                    ntf.delete()
                except:
                    pass
            else:
                print '[OK]'
                migrated += 1

    print
    print 'Migrated: %d/%d' % (migrated, total)
    print 'Failed: %d' % failed
    print
    print 'Completed %s' % ('with errors!' if failed else 'successfully!')
    print