Example #1
0
def create_notification(event=None, *args, **kwargs):

    if 'recipients' in kwargs:
        # mimic existing code so that when recipients is specified, no other system or personal notifications are sent.
        logger.debug('creating notifications for recipients')
        for recipient_notifications in Notifications.objects.filter(
                user__username__in=kwargs['recipients'],
                user__is_active=True,
                product=None):
            # kwargs.update({'user': recipient_notifications.user})
            process_notifications(event, recipient_notifications, *args,
                                  **kwargs)
    else:
        logger.debug('creating system notifications')
        # send system notifications to all admin users

        # System notifications
        try:
            system_notifications = Notifications.objects.get(user=None)
        except Exception:
            system_notifications = Notifications()

        admin_users = Dojo_User.objects.filter(is_staff=True)
        for admin_user in admin_users:
            system_notifications.user = admin_user
            process_notifications(event, system_notifications, *args, **kwargs)

        # Personal but global notifications
        # only retrieve users which have at least one notification type enabled for this event type.
        logger.debug('creating personal notifications')

        product = None
        if 'product' in kwargs:
            product = kwargs.get('product')

        if not product and 'engagement' in kwargs:
            product = kwargs['engagement'].product

        if not product and 'test' in kwargs:
            product = kwargs['test'].engagement.product

        # get users with either global notifications, or a product specific noditiciation
        users = Dojo_User.objects.filter(is_active=True).prefetch_related(
            Prefetch("notifications_set",
                     queryset=Notifications.objects.filter(
                         Q(product_id=product) | Q(product__isnull=True)),
                     to_attr="applicable_notifications")).annotate(
                         applicable_notifications_count=Count(
                             'notifications__id',
                             filter=Q(notifications__product_id=product)
                             | Q(notifications__product__isnull=True))).filter(
                                 applicable_notifications_count__gt=0)

        for user in users:
            # send notifications to user after merging possible multiple notifications records (i.e. personal global + personal product)
            # kwargs.update({'user': user})
            process_notifications(
                event,
                Notifications.merge_notifications_list(
                    user.applicable_notifications), *args, **kwargs)
Example #2
0
    def test_user_post_save_with_template(self, mock_notifications,
                                          mock_member, mock_settings):
        user = Dojo_User()
        user.id = 1

        group = Dojo_Group()
        group.id = 1

        template = Mock(Notifications(template=False, user=user))

        role = Role.objects.get(id=Roles.Reader)

        system_settings_group = System_Settings()
        system_settings_group.default_group = group
        system_settings_group.default_group_role = role

        mock_settings.get.return_value = system_settings_group
        save_mock_member = Mock(return_value=Dojo_Group_Member())
        mock_member.return_value = save_mock_member

        mock_notifications.objects.get.return_value = template

        user_post_save(None, user, True)

        mock_member.assert_called_with(group=group, user=user, role=role)
        save_mock_member.save.assert_called_once()

        mock_notifications.objects.get.assert_called_with(template=True)
        template.save.assert_called_once()
Example #3
0
    def test_user_post_save_without_template(self, mock_notifications,
                                             mock_member, mock_settings):
        user = Dojo_User()
        user.id = 1

        group = Dojo_Group()
        group.id = 1

        role = Role.objects.get(id=Roles.Reader)

        system_settings_group = System_Settings()
        system_settings_group.default_group = group
        system_settings_group.default_group_role = role

        mock_settings.get.return_value = system_settings_group
        save_mock_member = Mock(return_value=Dojo_Group_Member())
        mock_member.return_value = save_mock_member

        save_mock_notifications = Mock(return_value=Notifications())
        mock_notifications.return_value = save_mock_notifications
        mock_notifications.objects.get.side_effect = Exception(
            "Mock no templates")

        user_post_save(None, user, True)

        mock_member.assert_called_with(group=group, user=user, role=role)
        save_mock_member.save.assert_called_once()

        mock_notifications.assert_called_with(user=user)
        save_mock_notifications.save.assert_called_once()
Example #4
0
    def test_user_post_save_email_pattern_does_not_match(
            self, mock_notifications, mock_member, mock_settings):
        user = Dojo_User()
        user.id = 1
        user.email = '*****@*****.**'

        group = Dojo_Group()
        group.id = 1

        role = Role.objects.get(id=Roles.Reader)

        system_settings_group = System_Settings()
        system_settings_group.default_group = group
        system_settings_group.default_group_role = role
        system_settings_group.default_group_email_pattern = '.*@example.com'
        save_mock_notifications = Mock(return_value=Notifications())
        mock_notifications.return_value = save_mock_notifications
        mock_notifications.objects.get.side_effect = Exception(
            "Mock no templates")

        mock_settings.get.return_value = system_settings_group
        save_mock_member = Mock(return_value=Dojo_Group_Member())
        mock_member.return_value = save_mock_member

        user_post_save(None, user, True)

        mock_member.assert_not_called()
        save_mock_member.save.assert_not_called()
Example #5
0
def system_notifications(request):
    try:
        notifications_obj = Notifications.objects.get(user=None,
                                                      product__isnull=True)
    except:
        notifications_obj = Notifications(user=None)

    form = NotificationsForm(instance=notifications_obj)
    if request.method == 'POST':
        form = NotificationsForm(request.POST, instance=notifications_obj)
        if form.is_valid():
            new_settings = form.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Settings saved.',
                                 extra_tags='alert-success')

    add_breadcrumb(title="System notification settings",
                   top_level=False,
                   request=request)
    return render(
        request, 'dojo/notifications.html', {
            'form': form,
            'scope': 'system',
            'enabled_notifications': get_enabled_notifications_list(),
            'admin': request.user.is_superuser
        })
Example #6
0
def personal_notifications(request):
    try:
        notifications_obj = Notifications.objects.get(user=request.user)
    except:
        notifications_obj = Notifications(user=request.user)

    form = NotificationsForm(instance=notifications_obj)
    if request.method == 'POST':
        form = NotificationsForm(request.POST, instance=notifications_obj)
        if form.is_valid():
            new_settings = form.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Settings saved.',
                                 extra_tags='alert-success')

    add_breadcrumb(title="Personal notification settings",
                   top_level=False,
                   request=request)
    return render(request, 'dojo/notifications.html', {
        'form': form,
        'scope': 'personal',
        'admin': request.user.is_superuser
    })
Example #7
0
def create_notification(event=None, *args, **kwargs):
    if 'recipients' in kwargs:
        # mimic existing code so that when recipients is specified, no other system or personal notifications are sent.
        logger.debug('creating notifications for recipients')
        for recipient_notifications in Notifications.objects.filter(
                user__username__in=kwargs['recipients'],
                user__is_active=True,
                product=None):
            # kwargs.update({'user': recipient_notifications.user})
            process_notifications(event, recipient_notifications, *args,
                                  **kwargs)
    else:
        logger.debug('creating system notifications for event: %s', event)
        # send system notifications to all admin users

        # System notifications
        try:
            system_notifications = Notifications.objects.get(user=None)
        except Exception:
            system_notifications = Notifications()

        # System notifications are sent one with user=None, which will trigger email to configured system email, to global slack channel, etc.
        process_notifications(event, system_notifications, *args, **kwargs)

        # All admins will also receive system notifications, but as part of the person global notifications section below
        # This time user is set, so will trigger email to personal email, to personal slack channel (mention), etc.
        # only retrieve users which have at least one notification type enabled for this event type.
        logger.debug('creating personal notifications for event: %s', event)

        product = None
        if 'product' in kwargs:
            product = kwargs.get('product')

        if not product and 'engagement' in kwargs:
            product = kwargs['engagement'].product

        if not product and 'test' in kwargs:
            product = kwargs['test'].engagement.product

        if not product and 'finding' in kwargs:
            product = kwargs['finding'].test.engagement.product

        # get users with either global notifications, or a product specific noditiciation
        # and all admin/superuser, they will always be notified
        users = Dojo_User.objects.filter(is_active=True).prefetch_related(Prefetch(
            "notifications_set",
            queryset=Notifications.objects.filter(Q(product_id=product) | Q(product__isnull=True)),
            to_attr="applicable_notifications"
        )).annotate(applicable_notifications_count=Count('notifications__id', filter=Q(notifications__product_id=product) | Q(notifications__product__isnull=True)))\
            .filter((Q(applicable_notifications_count__gt=0) | Q(is_superuser=True) | Q(is_staff=True)))

        # only send to authorized users or admin/superusers
        if product:
            users = users.filter(
                Q(id__in=product.authorized_users.all())
                | Q(id__in=product.prod_type.authorized_users.all())
                | Q(is_superuser=True) | Q(is_staff=True))

        for user in users:
            # send notifications to user after merging possible multiple notifications records (i.e. personal global + personal product)
            # kwargs.update({'user': user})
            applicable_notifications = user.applicable_notifications
            if user.is_staff or user.is_superuser:
                # admin users get all system notifications
                applicable_notifications.append(system_notifications)

            notifications_set = Notifications.merge_notifications_list(
                applicable_notifications)
            notifications_set.user = user
            process_notifications(event, notifications_set, *args, **kwargs)
Example #8
0
    def test_merge_notifications_list(self):
        global_personal_notifications = Notifications(user=User.objects.get(username='******'))
        personal_product_notifications = Notifications(user=User.objects.get(username='******'), product=Product.objects.all()[0])

        global_personal_notifications.product_added = ['alert']
        global_personal_notifications.test_added = ''
        global_personal_notifications.scan_added = None
        global_personal_notifications.other = ['slack', 'mail']

        global_personal_notifications.save()  # we have to save it and retrieve it because only then the fields get turned into lists...

        global_personal_notifications = Notifications.objects.get(id=global_personal_notifications.id)

        # print(vars(global_personal_notifications))

        personal_product_notifications.product_added = ['mail']
        personal_product_notifications.test_added = ['mail', 'alert']
        personal_product_notifications.scan_added = None
        # print(vars(personal_product_notifications))

        personal_product_notifications.save()

        personal_product_notifications = Notifications.objects.get(id=personal_product_notifications.id)

        # print(vars(personal_product_notifications))

        merged_notifications = Notifications.merge_notifications_list([global_personal_notifications, personal_product_notifications])

        # print(vars(merged_notifications))

        self.assertEqual('alert' in merged_notifications.product_added, True)
        self.assertEqual('mail' in merged_notifications.product_added, True)
        self.assertEqual('slack' in merged_notifications.product_added, False)
        self.assertEqual(len(merged_notifications.product_added), 2)

        self.assertEqual('alert' in merged_notifications.test_added, True)
        self.assertEqual('mail' in merged_notifications.test_added, True)
        self.assertEqual('slack' in merged_notifications.test_added, False)
        self.assertEqual(len(merged_notifications.test_added), 2)

        self.assertEqual('alert' in merged_notifications.scan_added, False)
        self.assertEqual('mail' in merged_notifications.scan_added, False)
        self.assertEqual('slack' in merged_notifications.scan_added, False)
        self.assertEqual(len(merged_notifications.scan_added), 0)

        self.assertEqual('alert' in merged_notifications.other, True)
        self.assertEqual('mail' in merged_notifications.other, True)
        self.assertEqual('slack' in merged_notifications.other, True)  # default alert from global
        self.assertEqual(len(merged_notifications.other), 3)
Example #9
0
def create_notification(event=None, **kwargs):
    system_settings = System_Settings.objects.get()
    kwargs["system_settings"] = system_settings

    if 'recipients' in kwargs:
        # mimic existing code so that when recipients is specified, no other system or personal notifications are sent.
        logger.debug('creating notifications for recipients')
        for recipient_notifications in Notifications.objects.filter(
                user__username__in=kwargs['recipients'],
                user__is_active=True,
                product=None):
            # kwargs.update({'user': recipient_notifications.user})
            process_notifications(event, recipient_notifications, **kwargs)
    else:
        logger.debug('creating system notifications for event: %s', event)
        # send system notifications to all admin users

        # parse kwargs before converting them to dicts
        product_type = None
        if 'product_type' in kwargs:
            product_type = kwargs.get('product_type')

        product = None
        if 'product' in kwargs:
            product = kwargs.get('product')
        elif 'engagement' in kwargs:
            product = kwargs['engagement'].product
        elif 'test' in kwargs:
            product = kwargs['test'].engagement.product
        elif 'finding' in kwargs:
            product = kwargs['finding'].test.engagement.product
        elif 'obj' in kwargs:
            from dojo.utils import get_product
            product = get_product(kwargs['obj'])

        # System notifications
        try:
            system_notifications = Notifications.objects.get(user=None)
        except Exception:
            system_notifications = Notifications()

        # System notifications are sent one with user=None, which will trigger email to configured system email, to global slack channel, etc.
        process_notifications(event, system_notifications, **kwargs)

        # All admins will also receive system notifications, but as part of the person global notifications section below
        # This time user is set, so will trigger email to personal email, to personal slack channel (mention), etc.
        # only retrieve users which have at least one notification type enabled for this event type.
        logger.debug('creating personal notifications for event: %s', event)

        # There are notification like deleting a product type that shall not be sent to users.
        # These notifications will have the parameter no_users=True
        if not ('no_users' in kwargs and kwargs['no_users'] is True):
            # get users with either global notifications, or a product specific noditiciation
            # and all admin/superuser, they will always be notified
            users = Dojo_User.objects.filter(is_active=True).prefetch_related(Prefetch(
                "notifications_set",
                queryset=Notifications.objects.filter(Q(product_id=product) | Q(product__isnull=True)),
                to_attr="applicable_notifications"
            )).annotate(applicable_notifications_count=Count('notifications__id', filter=Q(notifications__product_id=product) | Q(notifications__product__isnull=True)))\
                .filter((Q(applicable_notifications_count__gt=0) | Q(is_superuser=True) | Q(is_staff=True)))

            # only send to authorized users or admin/superusers
            if product:
                users = get_authorized_users_for_product_and_product_type(
                    users, product, Permissions.Product_View)
            elif product_type:
                users = get_authorized_users_for_product_type(
                    users, product_type, Permissions.Product_Type_View)

            for user in users:
                # send notifications to user after merging possible multiple notifications records (i.e. personal global + personal product)
                # kwargs.update({'user': user})
                applicable_notifications = user.applicable_notifications
                if user.is_staff or user.is_superuser:
                    # admin users get all system notifications
                    applicable_notifications.append(system_notifications)

                notifications_set = Notifications.merge_notifications_list(
                    applicable_notifications)
                notifications_set.user = user
                process_notifications(event, notifications_set, **kwargs)
Example #10
0
def create_notification(event=None, **kwargs):
    def create_notification_message(event, notification_type):
        template = 'notifications/%s.tpl' % event.replace('/', '')
        kwargs.update({'type': notification_type})

        try:
            notification = render_to_string(template, kwargs)
        except:
            notification = render_to_string('notifications/other.tpl', kwargs)

        return notification

    def send_slack_notification(channel):
        try:
            res = requests.request(
                method='POST',
                url='https://slack.com/api/chat.postMessage',
                data={
                    'token': get_system_setting('slack_token'),
                    'channel': channel,
                    'username': get_system_setting('slack_username'),
                    'text': create_notification_message(event, 'slack')
                })
        except Exception as e:
            log_alert(e)
            pass

    def send_hipchat_notification(channel):
        try:
            # We use same template for HipChat as for slack
            res = requests.request(
                method='POST',
                url='https://%s/v2/room/%s/notification?auth_token=%s' %
                (get_system_setting('hipchat_site'), channel,
                 get_system_setting('hipchat_token')),
                data={
                    'message': create_notification_message(event, 'slack'),
                    'message_format': 'text'
                })
            print res
        except Exception as e:
            log_alert(e)
            pass

    def send_mail_notification(address):
        subject = '%s notification' % get_system_setting('team_name')
        if 'title' in kwargs:
            subject += ': %s' % kwargs['title']
        try:
            send_mail(subject,
                      create_notification_message(event, 'mail'),
                      get_system_setting('mail_notifications_from'), [address],
                      fail_silently=False)
        except Exception as e:
            log_alert(e)
            pass

    def send_alert_notification(user=None):
        icon = kwargs.get('icon', 'info-circle')
        alert = Alerts(
            user=user,
            title=kwargs.get('title'),
            description=create_notification_message(event, 'alert'),
            url=kwargs.get('url', reverse('alerts')),
            icon=icon,
            source=Notifications._meta.get_field(event).verbose_name.title())
        alert.save()

    def log_alert(e):
        alert = Alerts(user_id=Dojo_User.objects.get(is_superuser=True),
                       title='Notification issue',
                       description="%s" % e,
                       icon="exclamation-triangle",
                       source="Notifications")
        alert.save()

    # Global notifications
    try:
        notifications = Notifications.objects.get(user=None)
    except Exception as e:
        notifications = Notifications()

    slack_enabled = get_system_setting('enable_slack_notifications')
    hipchat_enabled = get_system_setting('enable_hipchat_notifications')
    mail_enabled = get_system_setting('enable_mail_notifications')

    if slack_enabled and 'slack' in getattr(notifications, event):
        send_slack_notification(get_system_setting('slack_channel'))

    if hipchat_enabled and 'hipchat' in getattr(notifications, event):
        send_hipchat_notification(get_system_setting('hipchat_channel'))

    if mail_enabled and 'mail' in getattr(notifications, event):
        send_slack_notification(get_system_setting('mail_notifications_from'))

    if 'alert' in getattr(notifications, event, None):
        send_alert_notification()

    # Personal notifications
    if 'recipients' in kwargs:
        users = User.objects.filter(username__in=kwargs['recipients'])
    else:
        users = User.objects.filter(is_superuser=True)
    for user in users:
        try:
            notifications = Notifications.objects.get(user=user)
        except Exception as e:
            notifications = Notifications()

        if slack_enabled and 'slack' in getattr(
                notifications,
                event) and user.usercontactinfo.slack_username is not None:
            send_slack_notification('@%s' %
                                    user.usercontactinfo.slack_username)

        # HipChat doesn't seem to offer direct message functionality, so no HipChat PM functionality here...

        if mail_enabled and 'mail' in getattr(notifications, event):
            send_mail_notification(user.email)

        if 'alert' in getattr(notifications, event):
            send_alert_notification(user)