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)
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()
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()
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()
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 })
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 })
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)
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)
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)
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)