diff --git a/dojo/db_migrations/0136_default_group_help_text.py b/dojo/db_migrations/0136_default_group_help_text.py new file mode 100644 index 00000000000..83785564474 --- /dev/null +++ b/dojo/db_migrations/0136_default_group_help_text.py @@ -0,0 +1,24 @@ +# Generated by Django 3.1.13 on 2021-11-25 17:25 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('dojo', '0135_email_from'), + ] + + operations = [ + migrations.AlterField( + model_name='system_settings', + name='default_group', + field=models.ForeignKey(blank=True, help_text='New users will be assigned to this group.', null=True, on_delete=django.db.models.deletion.RESTRICT, to='dojo.dojo_group'), + ), + migrations.AlterField( + model_name='system_settings', + name='default_group_role', + field=models.ForeignKey(blank=True, help_text='New users will be assigned to their default group with this role.', null=True, on_delete=django.db.models.deletion.RESTRICT, to='dojo.role'), + ), + ] diff --git a/dojo/models.py b/dojo/models.py index 73a204efe9d..0d79e08d22d 100755 --- a/dojo/models.py +++ b/dojo/models.py @@ -392,13 +392,13 @@ class System_Settings(models.Model): Dojo_Group, null=True, blank=True, - help_text="New users created by OAuth2 will be assigned to this group.", + help_text="New users will be assigned to this group.", on_delete=models.RESTRICT) default_group_role = models.ForeignKey( Role, null=True, blank=True, - help_text="New users created by OAuth2 will be assigned to their default group with this role.", + help_text="New users will be assigned to their default group with this role.", on_delete=models.RESTRICT) staff_user_email_pattern = models.CharField( max_length=200, diff --git a/dojo/pipeline.py b/dojo/pipeline.py index 655fd68e922..a346acf41ac 100644 --- a/dojo/pipeline.py +++ b/dojo/pipeline.py @@ -2,8 +2,7 @@ import re from django.conf import settings -from dojo.models import Dojo_Group_Member, Product, Product_Member, \ - Product_Type, System_Settings, Role +from dojo.models import Product, Product_Member, Product_Type, System_Settings, Role from social_core.backends.azuread_tenant import AzureADTenantOAuth2 from social_core.backends.google import GoogleOAuth2 from dojo.authorization.roles_permissions import Permissions, Roles @@ -60,14 +59,6 @@ def social_uid(backend, details, response, *args, **kwargs): def modify_permissions(backend, uid, user=None, social=None, *args, **kwargs): if kwargs.get('is_new'): system_settings = System_Settings.objects.get() - - if system_settings.default_group is not None and system_settings.default_group_role is not None: - dojo_group_member = Dojo_Group_Member( - group=system_settings.default_group, - user=user, - role=system_settings.default_group_role) - dojo_group_member.save() - if system_settings.staff_user_email_pattern is not None and \ re.fullmatch(system_settings.staff_user_email_pattern, user.email) is not None: user.is_staff = True diff --git a/dojo/unittests/test_pipeline.py b/dojo/unittests/test_pipeline.py index b3121156e23..1673eb12835 100644 --- a/dojo/unittests/test_pipeline.py +++ b/dojo/unittests/test_pipeline.py @@ -1,7 +1,6 @@ from django.test import TestCase -from unittest.mock import patch, Mock -from dojo.models import Dojo_Group_Member, Dojo_User, System_Settings, Dojo_Group, Role -from dojo.authorization.roles_permissions import Roles +from unittest.mock import patch +from dojo.models import Dojo_User, System_Settings from dojo.pipeline import modify_permissions @@ -12,18 +11,9 @@ def setUpTestData(cls): cls.user = Dojo_User() cls.user.id = 1 - cls.group = Dojo_Group() - cls.group.id = 1 - cls.system_settings_email = System_Settings() cls.system_settings_email.staff_user_email_pattern = '.*@example.com' - cls.role = Role.objects.get(id=Roles.Reader) - - cls.system_settings_group = System_Settings() - cls.system_settings_group.default_group = cls.group - cls.system_settings_group.default_group_role = cls.role - @patch('dojo.models.System_Settings.objects') def test_modify_permissions_user_is_staff(self, mock): mock.get.return_value = self.system_settings_email @@ -43,14 +33,3 @@ def test_modify_permissions_user_not_staff(self, mock): modify_permissions(backend=None, uid=None, user=self.user, is_new=True) self.assertFalse(self.user.is_staff) - - @patch('dojo.models.System_Settings.objects') - @patch('dojo.pipeline.Dojo_Group_Member') - def test_modify_permissions_default_group(self, mock_member, mock_settings): - mock_settings.get.return_value = self.system_settings_group - save_mock = Mock(return_value=Dojo_Group_Member()) - mock_member.return_value = save_mock - modify_permissions(backend=None, uid=None, user=self.user, is_new=True) - - mock_member.assert_called_with(group=self.group, user=self.user, role=self.role) - save_mock.save.assert_called_once() diff --git a/dojo/unittests/test_utils.py b/dojo/unittests/test_utils.py index 46b89463f7a..f3bcc8f4eb0 100644 --- a/dojo/unittests/test_utils.py +++ b/dojo/unittests/test_utils.py @@ -1,7 +1,11 @@ -from dojo.models import IMPORT_CLOSED_FINDING, IMPORT_CREATED_FINDING, IMPORT_REACTIVATED_FINDING, IMPORT_UPDATED_FINDING, Engagement, Product, Test, Test_Import, Test_Import_Finding_Action +from dojo.models import IMPORT_CLOSED_FINDING, IMPORT_CREATED_FINDING, IMPORT_REACTIVATED_FINDING, IMPORT_UPDATED_FINDING, \ + Engagement, Product, Test, Test_Import, Test_Import_Finding_Action, \ + Dojo_User, Dojo_Group, Dojo_Group_Member, Role, System_Settings, Notifications from contextlib import contextmanager from django.test import TestCase -from dojo.utils import dojo_crypto_encrypt, prepare_for_view +from unittest.mock import patch, Mock +from dojo.utils import dojo_crypto_encrypt, prepare_for_view, user_post_save +from dojo.authorization.roles_permissions import Roles import logging @@ -28,6 +32,36 @@ def test_encryption(self): test_output = prepare_for_view(encrypt) self.assertEqual(test_input, test_output) + @patch('dojo.models.System_Settings.objects') + @patch('dojo.utils.Dojo_Group_Member') + @patch('dojo.utils.Notifications') + def test_user_post_save(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 + + 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() + class assertNumOfModelsCreated(): def __init__(self, test_case, queryset, num): diff --git a/dojo/utils.py b/dojo/utils.py index 07372e59962..99009d05f21 100644 --- a/dojo/utils.py +++ b/dojo/utils.py @@ -26,7 +26,7 @@ from dojo.github import add_external_issue_github, update_external_issue_github, close_external_issue_github, reopen_external_issue_github from dojo.models import Finding, Engagement, Finding_Group, Finding_Template, Product, \ Dojo_User, Test, User, System_Settings, Notifications, Endpoint, Benchmark_Type, \ - Language_Type, Languages, Rule + Language_Type, Languages, Rule, Dojo_Group_Member from asteval import Interpreter from dojo.notifications.helper import create_notification import logging @@ -1641,15 +1641,25 @@ def get_site_url(): @receiver(post_save, sender=Dojo_User) -def set_default_notifications(sender, instance, created, **kwargs): - # for new user we create a Notifications object so the default 'alert' notifications work - # this needs to be a signal to make it also work for users created via ldap, oauth and other authentication backends +def user_post_save(sender, instance, created, **kwargs): + # For new users we create a Notifications object so the default 'alert' notifications work and + # assign them to a default group if specified in the system settings. + # This needs to be a signal to make it also work for users created via ldap, oauth and other + # authentication backends if created: logger.info('creating default set of notifications for: ' + str(instance)) - notifications = Notifications() - notifications.user = instance + notifications = Notifications(user=instance) notifications.save() + system_settings = System_Settings.objects.get() + if system_settings.default_group and system_settings.default_group_role: + logger.info('setting default group for: ' + str(instance)) + dojo_group_member = Dojo_Group_Member( + group=system_settings.default_group, + user=instance, + role=system_settings.default_group_role) + dojo_group_member.save() + @receiver(post_save, sender=Engagement) def engagement_post_Save(sender, instance, created, **kwargs):