#101 Team sharing form
* adds team sharing field to share form * splits sharing logic into user based and teams based * adds TeamAdmin for admin backend * adds validity check on Team name -> only unused names shall be valid
This commit is contained in:
		
							parent
							
								
									071bdea099
								
							
						
					
					
						commit
						e152dfd4d7
					
				@ -109,8 +109,8 @@ class APIV1CreateTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.eco_account.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
        self.eco_account.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        url = reverse("api:v1:deduction")
 | 
			
		||||
        json_file_path = "api/tests/v1/create/deduction_create_post_body.json"
 | 
			
		||||
 | 
			
		||||
@ -57,7 +57,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        test_intervention = self.create_dummy_intervention()
 | 
			
		||||
        test_intervention.share_with(self.superuser)
 | 
			
		||||
        test_intervention.share_with_user(self.superuser)
 | 
			
		||||
        url = reverse("api:v1:intervention", args=(str(test_intervention.id),))
 | 
			
		||||
        self._test_delete_object(test_intervention, url)
 | 
			
		||||
 | 
			
		||||
@ -68,7 +68,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        test_comp = self.create_dummy_compensation()
 | 
			
		||||
        test_comp.share_with(self.superuser)
 | 
			
		||||
        test_comp.share_with_user(self.superuser)
 | 
			
		||||
        url = reverse("api:v1:compensation", args=(str(test_comp.id),))
 | 
			
		||||
        self._test_delete_object(test_comp, url)
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        test_acc = self.create_dummy_eco_account()
 | 
			
		||||
        test_acc.share_with(self.superuser)
 | 
			
		||||
        test_acc.share_with_user(self.superuser)
 | 
			
		||||
        url = reverse("api:v1:ecoaccount", args=(str(test_acc.id),))
 | 
			
		||||
        self._test_delete_object(test_acc, url)
 | 
			
		||||
 | 
			
		||||
@ -90,7 +90,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        test_ema = self.create_dummy_ema()
 | 
			
		||||
        test_ema.share_with(self.superuser)
 | 
			
		||||
        test_ema.share_with_user(self.superuser)
 | 
			
		||||
        url = reverse("api:v1:ema", args=(str(test_ema.id),))
 | 
			
		||||
        self._test_delete_object(test_ema, url)
 | 
			
		||||
 | 
			
		||||
@ -101,7 +101,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        test_deduction = self.create_dummy_deduction()
 | 
			
		||||
        test_deduction.intervention.share_with(self.superuser)
 | 
			
		||||
        test_deduction.intervention.share_with_user(self.superuser)
 | 
			
		||||
        url = reverse("api:v1:deduction", args=(str(test_deduction.id),))
 | 
			
		||||
 | 
			
		||||
        response = self._run_delete_request(url)
 | 
			
		||||
 | 
			
		||||
@ -64,7 +64,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
        url = reverse("api:v1:intervention", args=(str(self.intervention.id),))
 | 
			
		||||
        geojson = self._test_get_object(self.intervention, url)
 | 
			
		||||
        self._assert_geojson_format(geojson)
 | 
			
		||||
@ -91,7 +91,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
        self.compensation.intervention = self.intervention
 | 
			
		||||
        self.compensation.save()
 | 
			
		||||
 | 
			
		||||
@ -119,7 +119,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.eco_account.share_with(self.superuser)
 | 
			
		||||
        self.eco_account.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        url = reverse("api:v1:ecoaccount", args=(str(self.eco_account.id),))
 | 
			
		||||
        geojson = self._test_get_object(self.eco_account, url)
 | 
			
		||||
@ -148,7 +148,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.ema.share_with(self.superuser)
 | 
			
		||||
        self.ema.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        url = reverse("api:v1:ema", args=(str(self.ema.id),))
 | 
			
		||||
        geojson = self._test_get_object(self.ema, url)
 | 
			
		||||
@ -172,7 +172,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.deduction.intervention.share_with(self.superuser)
 | 
			
		||||
        self.deduction.intervention.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        url = reverse("api:v1:deduction", args=(str(self.deduction.id),))
 | 
			
		||||
        _json = self._test_get_object(self.deduction, url)
 | 
			
		||||
 | 
			
		||||
@ -52,7 +52,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
        modified_on = self.intervention.modified
 | 
			
		||||
        url = reverse("api:v1:intervention", args=(str(self.intervention.id),))
 | 
			
		||||
        json_file_path = "api/tests/v1/update/intervention_update_put_body.json"
 | 
			
		||||
@ -79,7 +79,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        self.compensation.intervention = self.intervention
 | 
			
		||||
        self.compensation.save()
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        modified_on = self.compensation.modified
 | 
			
		||||
        url = reverse("api:v1:compensation", args=(str(self.compensation.id),))
 | 
			
		||||
@ -108,7 +108,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.eco_account.share_with(self.superuser)
 | 
			
		||||
        self.eco_account.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        modified_on = self.eco_account.modified
 | 
			
		||||
        url = reverse("api:v1:ecoaccount", args=(str(self.eco_account.id),))
 | 
			
		||||
@ -139,7 +139,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.ema.share_with(self.superuser)
 | 
			
		||||
        self.ema.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        modified_on = self.ema.modified
 | 
			
		||||
        url = reverse("api:v1:ema", args=(str(self.ema.id),))
 | 
			
		||||
@ -168,8 +168,8 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.deduction.intervention.share_with(self.superuser)
 | 
			
		||||
        self.deduction.account.share_with(self.superuser)
 | 
			
		||||
        self.deduction.intervention.share_with_user(self.superuser)
 | 
			
		||||
        self.deduction.account.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        url = reverse("api:v1:deduction", args=(str(self.deduction.id),))
 | 
			
		||||
        json_file_path = "api/tests/v1/update/deduction_update_put_body.json"
 | 
			
		||||
 | 
			
		||||
@ -292,7 +292,7 @@ class AbstractModelShareAPIView(AbstractAPIView):
 | 
			
		||||
                id__in=obj.shared_users
 | 
			
		||||
            )
 | 
			
		||||
            new_users_objs = obj.shared_users.union(new_users_to_be_added)
 | 
			
		||||
        obj.share_with_list(new_users_objs)
 | 
			
		||||
        obj.share_with_user_list(new_users_objs)
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -400,7 +400,7 @@ class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMix
 | 
			
		||||
                comment=comment,
 | 
			
		||||
                legal=legal
 | 
			
		||||
            )
 | 
			
		||||
            acc.share_with(user)
 | 
			
		||||
            acc.share_with_user(user)
 | 
			
		||||
 | 
			
		||||
            # Add the log entry to the main objects log list
 | 
			
		||||
            acc.log.add(action)
 | 
			
		||||
 | 
			
		||||
@ -103,7 +103,7 @@ class CompensationViewTestCase(BaseViewTestCase):
 | 
			
		||||
        client = Client()
 | 
			
		||||
        client.login(username=self.superuser.username, password=self.superuser_pw)
 | 
			
		||||
        self.superuser.groups.set([])
 | 
			
		||||
        self.intervention.share_with_list([self.superuser])
 | 
			
		||||
        self.intervention.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        # Since the user has no groups, it does not matter that data has been shared. There SHOULD not be any difference
 | 
			
		||||
        # to a user without access, since the important permissions are missing
 | 
			
		||||
@ -143,7 +143,7 @@ class CompensationViewTestCase(BaseViewTestCase):
 | 
			
		||||
        client.login(username=self.superuser.username, password=self.superuser_pw)
 | 
			
		||||
        self.superuser.groups.set([])
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.intervention.share_with_list([])
 | 
			
		||||
        self.intervention.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        # Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
 | 
			
		||||
        # to a user having shared access, since all important permissions are missing
 | 
			
		||||
@ -185,7 +185,7 @@ class CompensationViewTestCase(BaseViewTestCase):
 | 
			
		||||
        group = self.groups.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([group])
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.intervention.share_with_list([self.superuser])
 | 
			
		||||
        self.intervention.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -221,7 +221,7 @@ class CompensationViewTestCase(BaseViewTestCase):
 | 
			
		||||
        group = self.groups.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([group])
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.intervention.share_with_list([])
 | 
			
		||||
        self.intervention.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
        super().setUp()
 | 
			
		||||
 | 
			
		||||
        # Give the user shared access to the dummy intervention -> inherits the access to the compensation
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        # Make sure the intervention itself would be fine with valid data
 | 
			
		||||
        self.intervention = self.fill_out_intervention(self.intervention)
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
 | 
			
		||||
        client = Client()
 | 
			
		||||
        client.login(username=self.superuser.username, password=self.superuser_pw)
 | 
			
		||||
        self.superuser.groups.set([])
 | 
			
		||||
        self.eco_account.share_with_list([self.superuser])
 | 
			
		||||
        self.eco_account.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        # Since the user has no groups, it does not matter that data has been shared. There SHOULD not be any difference
 | 
			
		||||
        # to a user without access, since the important permissions are missing
 | 
			
		||||
@ -119,7 +119,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
 | 
			
		||||
        client = Client()
 | 
			
		||||
        client.login(username=self.superuser.username, password=self.superuser_pw)
 | 
			
		||||
        self.superuser.groups.set([])
 | 
			
		||||
        self.eco_account.share_with_list([])
 | 
			
		||||
        self.eco_account.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        # Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
 | 
			
		||||
        # to a user having shared access, since all important permissions are missing
 | 
			
		||||
@ -163,7 +163,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
 | 
			
		||||
        group = self.groups.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([group])
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.eco_account.share_with_list([self.superuser])
 | 
			
		||||
        self.eco_account.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -200,7 +200,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
 | 
			
		||||
        client.login(username=self.superuser.username, password=self.superuser_pw)
 | 
			
		||||
        group = self.groups.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([group])
 | 
			
		||||
        self.eco_account.share_with_list([])
 | 
			
		||||
        self.eco_account.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
        # Add user to conservation office group and give shared access to the account
 | 
			
		||||
        self.superuser.groups.add(self.groups.get(name=DEFAULT_GROUP))
 | 
			
		||||
        self.superuser.groups.add(self.groups.get(name=ETS_GROUP))
 | 
			
		||||
        self.eco_account.share_with_list([self.superuser])
 | 
			
		||||
        self.eco_account.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
    def test_new(self):
 | 
			
		||||
        """ Test the creation of an EcoAccount
 | 
			
		||||
@ -73,7 +73,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.eco_account.share_with(self.superuser)
 | 
			
		||||
        self.eco_account.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        url = reverse("compensation:acc:edit", args=(self.eco_account.id,))
 | 
			
		||||
        pre_edit_log_count = self.eco_account.log.count()
 | 
			
		||||
@ -129,7 +129,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        # Add proper privilege for the user
 | 
			
		||||
        self.eco_account.share_with(self.superuser)
 | 
			
		||||
        self.eco_account.share_with_user(self.superuser)
 | 
			
		||||
        pre_record_log_count = self.eco_account.log.count()
 | 
			
		||||
 | 
			
		||||
        # Prepare url and form data
 | 
			
		||||
@ -178,7 +178,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        # Give user shared access to the dummy intervention, which will be needed here
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
        pre_deduction_acc_log_count = self.eco_account.log.count()
 | 
			
		||||
        pre_deduction_int_log_count = self.intervention.log.count()
 | 
			
		||||
 | 
			
		||||
@ -231,7 +231,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
    def test_edit_deduction(self):
 | 
			
		||||
        test_surface = self.eco_account.get_available_rest()[0]
 | 
			
		||||
        self.eco_account.set_recorded(self.superuser)
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
        self.eco_account.refresh_from_db()
 | 
			
		||||
        self.assertIn(self.superuser, self.intervention.is_shared_with(self.superuser))
 | 
			
		||||
 | 
			
		||||
@ -281,8 +281,8 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
            "confirm": True,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        intervention.share_with(self.superuser)
 | 
			
		||||
        account.share_with(self.superuser)
 | 
			
		||||
        intervention.share_with_user(self.superuser)
 | 
			
		||||
        account.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        pre_edit_intervention_log_count = intervention.log.count()
 | 
			
		||||
        pre_edit_account_log_count = account.log.count()
 | 
			
		||||
 | 
			
		||||
@ -64,7 +64,7 @@ class PaymentViewTestCase(BaseViewTestCase):
 | 
			
		||||
        client = Client()
 | 
			
		||||
        client.login(username=self.superuser.username, password=self.superuser_pw)
 | 
			
		||||
        self.superuser.groups.set([])
 | 
			
		||||
        self.intervention.share_with_list([self.superuser])
 | 
			
		||||
        self.intervention.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        # Since the user has no groups, it does not matter that data has been shared. There SHOULD not be any difference
 | 
			
		||||
        # to a user without access, since the important permissions are missing
 | 
			
		||||
@ -91,7 +91,7 @@ class PaymentViewTestCase(BaseViewTestCase):
 | 
			
		||||
        client.login(username=self.superuser.username, password=self.superuser_pw)
 | 
			
		||||
        self.superuser.groups.set([])
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.intervention.share_with_list([])
 | 
			
		||||
        self.intervention.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        # Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
 | 
			
		||||
        # to a user having shared access, since all important permissions are missing
 | 
			
		||||
@ -120,7 +120,7 @@ class PaymentViewTestCase(BaseViewTestCase):
 | 
			
		||||
        group = self.groups.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([group])
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.intervention.share_with_list([self.superuser])
 | 
			
		||||
        self.intervention.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.new_url,
 | 
			
		||||
@ -143,7 +143,7 @@ class PaymentViewTestCase(BaseViewTestCase):
 | 
			
		||||
        group = self.groups.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([group])
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.intervention.share_with_list([])
 | 
			
		||||
        self.intervention.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@ class PaymentWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
    def setUp(self) -> None:
 | 
			
		||||
        super().setUp()
 | 
			
		||||
        # Give the user shared access to the dummy intervention
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
        self.payment = Payment.objects.get_or_create(
 | 
			
		||||
            intervention=self.intervention,
 | 
			
		||||
 | 
			
		||||
@ -796,7 +796,7 @@ def share_view(request: HttpRequest, id: str, token: str):
 | 
			
		||||
                request,
 | 
			
		||||
                _("{} has been shared with you").format(obj.identifier)
 | 
			
		||||
            )
 | 
			
		||||
            obj.share_with(user)
 | 
			
		||||
            obj.share_with_user(user)
 | 
			
		||||
        return redirect("compensation:acc:detail", id=id)
 | 
			
		||||
    else:
 | 
			
		||||
        messages.error(
 | 
			
		||||
 | 
			
		||||
@ -80,7 +80,7 @@ class NewEmaForm(AbstractCompensationForm, CompensationResponsibleFormMixin):
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            # Add the creating user to the list of shared users
 | 
			
		||||
            acc.share_with(user)
 | 
			
		||||
            acc.share_with_user(user)
 | 
			
		||||
 | 
			
		||||
            # Add the log entry to the main objects log list
 | 
			
		||||
            acc.log.add(action)
 | 
			
		||||
 | 
			
		||||
@ -110,7 +110,7 @@ class EmaViewTestCase(CompensationViewTestCase):
 | 
			
		||||
 | 
			
		||||
        # Sharing does not have any effect in here, since the default group will prohibit further functionality access
 | 
			
		||||
        # to this user
 | 
			
		||||
        self.ema.share_with_list([self.superuser])
 | 
			
		||||
        self.ema.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -160,7 +160,7 @@ class EmaViewTestCase(CompensationViewTestCase):
 | 
			
		||||
 | 
			
		||||
        # Sharing does not have any effect in here, since the default group will prohibit further functionality access
 | 
			
		||||
        # to this user
 | 
			
		||||
        self.ema.share_with_list([])
 | 
			
		||||
        self.ema.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -203,7 +203,7 @@ class EmaViewTestCase(CompensationViewTestCase):
 | 
			
		||||
        groups = self.groups.filter(Q(name=ETS_GROUP)|Q(name=DEFAULT_GROUP))
 | 
			
		||||
        self.superuser.groups.set(groups)
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.ema.share_with_list([self.superuser])
 | 
			
		||||
        self.ema.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -243,7 +243,7 @@ class EmaViewTestCase(CompensationViewTestCase):
 | 
			
		||||
        groups = self.groups.filter(Q(name=ETS_GROUP)|Q(name=DEFAULT_GROUP))
 | 
			
		||||
        self.superuser.groups.set(groups)
 | 
			
		||||
        # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
 | 
			
		||||
        self.ema.share_with_list([])
 | 
			
		||||
        self.ema.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
 | 
			
		||||
@ -621,7 +621,7 @@ def share_view(request: HttpRequest, id: str, token: str):
 | 
			
		||||
                request,
 | 
			
		||||
                _("{} has been shared with you").format(obj.identifier)
 | 
			
		||||
            )
 | 
			
		||||
            obj.share_with(user)
 | 
			
		||||
            obj.share_with_user(user)
 | 
			
		||||
        return redirect("ema:detail", id=id)
 | 
			
		||||
    else:
 | 
			
		||||
        messages.error(
 | 
			
		||||
 | 
			
		||||
@ -253,7 +253,7 @@ class NewInterventionForm(BaseForm):
 | 
			
		||||
            intervention.log.add(action)
 | 
			
		||||
 | 
			
		||||
            # Add the performing user as the first user having access to the data
 | 
			
		||||
            intervention.share_with(user)
 | 
			
		||||
            intervention.share_with_user(user)
 | 
			
		||||
        return intervention
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -115,7 +115,7 @@ class ShareModalForm(BaseModalForm):
 | 
			
		||||
 | 
			
		||||
    def _add_teams_to_field(self):
 | 
			
		||||
        form_data = {
 | 
			
		||||
            "teams": []
 | 
			
		||||
            "team_select": self.instance.teams.all()
 | 
			
		||||
        }
 | 
			
		||||
        self.load_initial_data(form_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -144,7 +144,7 @@ class InterventionViewTestCase(BaseViewTestCase):
 | 
			
		||||
        # Add user to default group
 | 
			
		||||
        default_group = Group.objects.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([default_group])
 | 
			
		||||
        self.intervention.share_with_list([self.superuser])
 | 
			
		||||
        self.intervention.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -190,7 +190,7 @@ class InterventionViewTestCase(BaseViewTestCase):
 | 
			
		||||
        # Add user to default group
 | 
			
		||||
        default_group = Group.objects.get(name=DEFAULT_GROUP)
 | 
			
		||||
        self.superuser.groups.set([default_group])
 | 
			
		||||
        self.intervention.share_with_list([])
 | 
			
		||||
        self.intervention.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -236,7 +236,7 @@ class InterventionViewTestCase(BaseViewTestCase):
 | 
			
		||||
        # Add user to zb group
 | 
			
		||||
        zb_group = self.groups.get(name=ZB_GROUP)
 | 
			
		||||
        self.superuser.groups.set([zb_group])
 | 
			
		||||
        self.intervention.share_with_list([self.superuser])
 | 
			
		||||
        self.intervention.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -282,7 +282,7 @@ class InterventionViewTestCase(BaseViewTestCase):
 | 
			
		||||
        # Add user to zb group
 | 
			
		||||
        zb_group = self.groups.get(name=ZB_GROUP)
 | 
			
		||||
        self.superuser.groups.set([zb_group])
 | 
			
		||||
        self.intervention.share_with_list([])
 | 
			
		||||
        self.intervention.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -328,7 +328,7 @@ class InterventionViewTestCase(BaseViewTestCase):
 | 
			
		||||
        # Add user to ets group
 | 
			
		||||
        ets_group = Group.objects.get(name=ETS_GROUP)
 | 
			
		||||
        self.superuser.groups.set([ets_group])
 | 
			
		||||
        self.intervention.share_with_list([self.superuser])
 | 
			
		||||
        self.intervention.share_with_user_list([self.superuser])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
@ -374,7 +374,7 @@ class InterventionViewTestCase(BaseViewTestCase):
 | 
			
		||||
        # Add user to default group
 | 
			
		||||
        ets_group = Group.objects.get(name=ETS_GROUP)
 | 
			
		||||
        self.superuser.groups.set([ets_group])
 | 
			
		||||
        self.intervention.share_with_list([])
 | 
			
		||||
        self.intervention.share_with_user_list([])
 | 
			
		||||
 | 
			
		||||
        success_urls = [
 | 
			
		||||
            self.index_url,
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
        super().setUp()
 | 
			
		||||
        # Recreate a new (bare minimum) intervention before each test
 | 
			
		||||
        self.intervention = self.create_dummy_intervention()
 | 
			
		||||
        self.intervention.share_with(self.superuser)
 | 
			
		||||
        self.intervention.share_with_user(self.superuser)
 | 
			
		||||
 | 
			
		||||
    def test_new(self):
 | 
			
		||||
        """
 | 
			
		||||
@ -365,7 +365,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
 | 
			
		||||
        if self.eco_account.recorded is None:
 | 
			
		||||
            rec_action = UserActionLogEntry.get_recorded_action(self.superuser)
 | 
			
		||||
            self.eco_account.recorded = rec_action
 | 
			
		||||
        self.eco_account.share_with_list([self.superuser])
 | 
			
		||||
        self.eco_account.share_with_user_list([self.superuser])
 | 
			
		||||
        self.eco_account.save()
 | 
			
		||||
        num_all_deducs = EcoAccountDeduction.objects.count()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -432,7 +432,7 @@ def share_view(request: HttpRequest, id: str, token: str):
 | 
			
		||||
                request,
 | 
			
		||||
                _("{} has been shared with you").format(intervention.identifier)
 | 
			
		||||
            )
 | 
			
		||||
            intervention.share_with(user)
 | 
			
		||||
            intervention.share_with_user(user)
 | 
			
		||||
        return redirect("intervention:detail", id=id)
 | 
			
		||||
    else:
 | 
			
		||||
        messages.error(
 | 
			
		||||
 | 
			
		||||
@ -378,6 +378,7 @@ class CheckableObjectMixin(models.Model):
 | 
			
		||||
class ShareableObjectMixin(models.Model):
 | 
			
		||||
    # Users having access on this object
 | 
			
		||||
    users = models.ManyToManyField("user.User", help_text="Users having access (data shared with)")
 | 
			
		||||
    teams = models.ManyToManyField("user.Team", help_text="Teams having access (data shared with)")
 | 
			
		||||
    access_token = models.CharField(
 | 
			
		||||
        max_length=255,
 | 
			
		||||
        null=True,
 | 
			
		||||
@ -435,9 +436,36 @@ class ShareableObjectMixin(models.Model):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        return self.users.filter(id=user.id)
 | 
			
		||||
        directly_shared = self.users.filter(id=user.id).exists()
 | 
			
		||||
        team_shared = self.teams.filter(
 | 
			
		||||
            users__in=[user]
 | 
			
		||||
        ).exists()
 | 
			
		||||
        is_shared = directly_shared or team_shared
 | 
			
		||||
        return is_shared
 | 
			
		||||
 | 
			
		||||
    def share_with(self, user):
 | 
			
		||||
    def share_with_team(self, team):
 | 
			
		||||
        """ Adds team to list of shared access teans
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            team (Team): The team to be added to the object
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.teams.add(team)
 | 
			
		||||
 | 
			
		||||
    def share_with_team_list(self, team_list: list):
 | 
			
		||||
        """ Sets the list of shared access teams
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            team_list (list): The teams to be added to the object
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.teams.set(team_list)
 | 
			
		||||
 | 
			
		||||
    def share_with_user(self, user):
 | 
			
		||||
        """ Adds user to list of shared access users
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
@ -449,7 +477,7 @@ class ShareableObjectMixin(models.Model):
 | 
			
		||||
        if not self.is_shared_with(user):
 | 
			
		||||
            self.users.add(user)
 | 
			
		||||
 | 
			
		||||
    def share_with_list(self, user_list: list):
 | 
			
		||||
    def share_with_user_list(self, user_list: list):
 | 
			
		||||
        """ Sets the list of shared access users
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
@ -472,24 +500,32 @@ class ShareableObjectMixin(models.Model):
 | 
			
		||||
        from user.models import User
 | 
			
		||||
        form_data = form.cleaned_data
 | 
			
		||||
 | 
			
		||||
        keep_accessing_users = form_data["users"]
 | 
			
		||||
        # Fetch selected teams and find out which user IDs are in removed teams -> mails need to be sent
 | 
			
		||||
        accessing_teams = form_data["team_select"]
 | 
			
		||||
        removed_team_users = self.teams.all().exclude(
 | 
			
		||||
            id__in=accessing_teams
 | 
			
		||||
        ).values_list("users__id", flat=True)
 | 
			
		||||
 | 
			
		||||
        new_accessing_users = list(form_data["user_select"].values_list("id", flat=True))
 | 
			
		||||
        keep_accessing_users = form_data["users"]
 | 
			
		||||
        accessing_users = keep_accessing_users + new_accessing_users
 | 
			
		||||
        users = User.objects.filter(
 | 
			
		||||
            id__in=accessing_users
 | 
			
		||||
        )
 | 
			
		||||
        removed_users = self.users.all().exclude(
 | 
			
		||||
            id__in=accessing_users
 | 
			
		||||
        ).values("id")
 | 
			
		||||
        ).values_list("id", flat=True)
 | 
			
		||||
        removed_users = removed_users.union(removed_team_users)
 | 
			
		||||
 | 
			
		||||
        # Send mails
 | 
			
		||||
        for user in removed_users:
 | 
			
		||||
            celery_send_mail_shared_access_removed.delay(self.identifier, self.title, user["id"])
 | 
			
		||||
        for user in new_accessing_users:
 | 
			
		||||
            celery_send_mail_shared_access_given.delay(self.identifier, self.title,  user)
 | 
			
		||||
        for user_id in removed_users:
 | 
			
		||||
            celery_send_mail_shared_access_removed.delay(self.identifier, self.title, user_id)
 | 
			
		||||
        for user_id in new_accessing_users:
 | 
			
		||||
            celery_send_mail_shared_access_given.delay(self.identifier, self.title,  user_id)
 | 
			
		||||
 | 
			
		||||
        # Set new shared users
 | 
			
		||||
        self.share_with_list(users)
 | 
			
		||||
        self.share_with_user_list(users)
 | 
			
		||||
        self.share_with_team_list(accessing_teams)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def shared_users(self) -> QuerySet:
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@ -7,8 +7,8 @@
 | 
			
		||||
#: compensation/forms/modalForms.py:47 compensation/forms/modalForms.py:63
 | 
			
		||||
#: compensation/forms/modalForms.py:356 compensation/forms/modalForms.py:463
 | 
			
		||||
#: intervention/forms/forms.py:54 intervention/forms/forms.py:156
 | 
			
		||||
#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:127
 | 
			
		||||
#: intervention/forms/modalForms.py:140 intervention/forms/modalForms.py:153
 | 
			
		||||
#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:148
 | 
			
		||||
#: intervention/forms/modalForms.py:161 intervention/forms/modalForms.py:174
 | 
			
		||||
#: konova/filters/mixins.py:53 konova/filters/mixins.py:54
 | 
			
		||||
#: konova/filters/mixins.py:81 konova/filters/mixins.py:82
 | 
			
		||||
#: konova/filters/mixins.py:94 konova/filters/mixins.py:95
 | 
			
		||||
@ -26,7 +26,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: PACKAGE VERSION\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2022-02-17 13:42+0100\n"
 | 
			
		||||
"POT-Creation-Date: 2022-02-18 09:35+0100\n"
 | 
			
		||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
			
		||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
			
		||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
			
		||||
@ -64,7 +64,7 @@ msgstr "Verantwortliche Stelle"
 | 
			
		||||
#: compensation/forms/forms.py:165 intervention/forms/forms.py:64
 | 
			
		||||
#: intervention/forms/forms.py:81 intervention/forms/forms.py:97
 | 
			
		||||
#: intervention/forms/forms.py:113 intervention/forms/modalForms.py:49
 | 
			
		||||
#: user/forms.py:196
 | 
			
		||||
#: intervention/forms/modalForms.py:63 user/forms.py:196
 | 
			
		||||
msgid "Click for selection"
 | 
			
		||||
msgstr "Auswählen..."
 | 
			
		||||
 | 
			
		||||
@ -221,7 +221,7 @@ msgstr "Abbuchungen"
 | 
			
		||||
#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:36
 | 
			
		||||
#: ema/templates/ema/detail/includes/states-after.html:36
 | 
			
		||||
#: ema/templates/ema/detail/includes/states-before.html:36
 | 
			
		||||
#: intervention/forms/modalForms.py:338
 | 
			
		||||
#: intervention/forms/modalForms.py:359
 | 
			
		||||
msgid "Surface"
 | 
			
		||||
msgstr "Fläche"
 | 
			
		||||
 | 
			
		||||
@ -284,8 +284,8 @@ msgid "Type"
 | 
			
		||||
msgstr "Typ"
 | 
			
		||||
 | 
			
		||||
#: analysis/templates/analysis/reports/includes/old_data/amount.html:24
 | 
			
		||||
#: compensation/tables.py:89 intervention/forms/modalForms.py:349
 | 
			
		||||
#: intervention/forms/modalForms.py:356 intervention/tables.py:88
 | 
			
		||||
#: compensation/tables.py:89 intervention/forms/modalForms.py:370
 | 
			
		||||
#: intervention/forms/modalForms.py:377 intervention/tables.py:88
 | 
			
		||||
#: intervention/templates/intervention/detail/view.html:19
 | 
			
		||||
#: konova/templates/konova/includes/quickstart/interventions.html:4
 | 
			
		||||
#: templates/navbars/navbar.html:22
 | 
			
		||||
@ -295,7 +295,7 @@ msgstr "Eingriff"
 | 
			
		||||
#: analysis/templates/analysis/reports/includes/old_data/amount.html:34
 | 
			
		||||
#: compensation/tables.py:266
 | 
			
		||||
#: compensation/templates/compensation/detail/eco_account/view.html:20
 | 
			
		||||
#: intervention/forms/modalForms.py:322 intervention/forms/modalForms.py:329
 | 
			
		||||
#: intervention/forms/modalForms.py:343 intervention/forms/modalForms.py:350
 | 
			
		||||
#: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
 | 
			
		||||
#: templates/navbars/navbar.html:34
 | 
			
		||||
msgid "Eco-account"
 | 
			
		||||
@ -364,7 +364,7 @@ msgstr "Kompensation XY; Flur ABC"
 | 
			
		||||
#: ema/templates/ema/detail/includes/actions.html:34
 | 
			
		||||
#: ema/templates/ema/detail/includes/deadlines.html:34
 | 
			
		||||
#: ema/templates/ema/detail/includes/documents.html:34
 | 
			
		||||
#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:152
 | 
			
		||||
#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:173
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/documents.html:34
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/payments.html:34
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/revocation.html:38
 | 
			
		||||
@ -484,7 +484,7 @@ msgid "Due on which date"
 | 
			
		||||
msgstr "Zahlung wird an diesem Datum erwartet"
 | 
			
		||||
 | 
			
		||||
#: compensation/forms/modalForms.py:64 compensation/forms/modalForms.py:357
 | 
			
		||||
#: intervention/forms/modalForms.py:154 konova/forms.py:395
 | 
			
		||||
#: intervention/forms/modalForms.py:175 konova/forms.py:395
 | 
			
		||||
msgid "Additional comment, maximum {} letters"
 | 
			
		||||
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
 | 
			
		||||
 | 
			
		||||
@ -512,7 +512,7 @@ msgstr "Zusatzbezeichnung"
 | 
			
		||||
msgid "Select an additional biotope type"
 | 
			
		||||
msgstr "Zusatzbezeichnung wählen"
 | 
			
		||||
 | 
			
		||||
#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:340
 | 
			
		||||
#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:361
 | 
			
		||||
msgid "in m²"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
@ -540,7 +540,7 @@ msgstr "Fristart wählen"
 | 
			
		||||
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
 | 
			
		||||
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
 | 
			
		||||
#: ema/templates/ema/detail/includes/deadlines.html:31
 | 
			
		||||
#: intervention/forms/modalForms.py:126
 | 
			
		||||
#: intervention/forms/modalForms.py:147
 | 
			
		||||
msgid "Date"
 | 
			
		||||
msgstr "Datum"
 | 
			
		||||
 | 
			
		||||
@ -752,7 +752,7 @@ msgstr "Menge"
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/documents.html:39
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/payments.html:39
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/revocation.html:43
 | 
			
		||||
#: templates/log.html:10 user/templates/user/team/index.html:33
 | 
			
		||||
#: templates/log.html:10 user/templates/user/team/index.html:32
 | 
			
		||||
msgid "Action"
 | 
			
		||||
msgstr "Aktionen"
 | 
			
		||||
 | 
			
		||||
@ -1000,14 +1000,14 @@ msgstr "Zuletzt bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: compensation/templates/compensation/detail/compensation/view.html:100
 | 
			
		||||
#: compensation/templates/compensation/detail/eco_account/view.html:83
 | 
			
		||||
#: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:56
 | 
			
		||||
#: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:70
 | 
			
		||||
#: intervention/templates/intervention/detail/view.html:116
 | 
			
		||||
msgid "Shared with"
 | 
			
		||||
msgstr "Freigegeben für"
 | 
			
		||||
 | 
			
		||||
#: compensation/templates/compensation/detail/eco_account/includes/controls.html:15
 | 
			
		||||
#: ema/templates/ema/detail/includes/controls.html:15
 | 
			
		||||
#: intervention/forms/modalForms.py:70
 | 
			
		||||
#: intervention/forms/modalForms.py:84
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/controls.html:15
 | 
			
		||||
msgid "Share"
 | 
			
		||||
msgstr "Freigabe"
 | 
			
		||||
@ -1325,10 +1325,22 @@ msgid "Send this link to users who you want to have writing access on the data"
 | 
			
		||||
msgstr "Andere Nutzer erhalten über diesen Link Zugriff auf die Daten"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:41
 | 
			
		||||
msgid "Add team to share with"
 | 
			
		||||
msgstr "Team hinzufügen"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:43
 | 
			
		||||
msgid ""
 | 
			
		||||
"Multiple selection possible - You can only select teams which do not already "
 | 
			
		||||
"have access."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Mehrfachauswahl möglich - Sie können nur Teams wählen, für die der Eintrag "
 | 
			
		||||
"noch nicht freigegeben wurde."
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:55
 | 
			
		||||
msgid "Add user to share with"
 | 
			
		||||
msgstr "Nutzer direkt hinzufügen"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:43
 | 
			
		||||
#: intervention/forms/modalForms.py:57
 | 
			
		||||
msgid ""
 | 
			
		||||
"Multiple selection possible - You can only select users which do not already "
 | 
			
		||||
"have access. Enter the full username."
 | 
			
		||||
@ -1336,46 +1348,46 @@ msgstr ""
 | 
			
		||||
"Mehrfachauswahl möglich - Sie können nur Nutzer wählen, für die der Eintrag "
 | 
			
		||||
"noch nicht freigegeben wurde. Geben Sie den ganzen Nutzernamen an."
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:59
 | 
			
		||||
#: intervention/forms/modalForms.py:73
 | 
			
		||||
msgid "Remove check to remove access for this user"
 | 
			
		||||
msgstr "Wählen Sie die Nutzer ab, die keinen Zugriff mehr haben sollen"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:71
 | 
			
		||||
#: intervention/forms/modalForms.py:85
 | 
			
		||||
msgid "Share settings for {}"
 | 
			
		||||
msgstr "Freigabe Einstellungen für {}"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:128
 | 
			
		||||
#: intervention/forms/modalForms.py:149
 | 
			
		||||
msgid "Date of revocation"
 | 
			
		||||
msgstr "Datum des Widerspruchs"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:139
 | 
			
		||||
#: intervention/forms/modalForms.py:160
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/revocation.html:35
 | 
			
		||||
msgid "Document"
 | 
			
		||||
msgstr "Dokument"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:142
 | 
			
		||||
#: intervention/forms/modalForms.py:163
 | 
			
		||||
msgid "Must be smaller than 15 Mb"
 | 
			
		||||
msgstr "Muss kleiner als 15 Mb sein"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:167
 | 
			
		||||
#: intervention/forms/modalForms.py:188
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/revocation.html:18
 | 
			
		||||
msgid "Add revocation"
 | 
			
		||||
msgstr "Widerspruch hinzufügen"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:224
 | 
			
		||||
#: intervention/forms/modalForms.py:245
 | 
			
		||||
msgid "Checked intervention data"
 | 
			
		||||
msgstr "Eingriffsdaten geprüft"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:230
 | 
			
		||||
#: intervention/forms/modalForms.py:251
 | 
			
		||||
msgid "Checked compensations data and payments"
 | 
			
		||||
msgstr "Kompensationen und Zahlungen geprüft"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:239
 | 
			
		||||
#: intervention/forms/modalForms.py:260
 | 
			
		||||
#: intervention/templates/intervention/detail/includes/controls.html:19
 | 
			
		||||
msgid "Run check"
 | 
			
		||||
msgstr "Prüfung vornehmen"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:240 konova/forms.py:514
 | 
			
		||||
#: intervention/forms/modalForms.py:261 konova/forms.py:514
 | 
			
		||||
msgid ""
 | 
			
		||||
"I, {} {}, confirm that all necessary control steps have been performed by "
 | 
			
		||||
"myself."
 | 
			
		||||
@ -1383,23 +1395,23 @@ msgstr ""
 | 
			
		||||
"Ich, {} {}, bestätige, dass die notwendigen Kontrollschritte durchgeführt "
 | 
			
		||||
"wurden:"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:324
 | 
			
		||||
#: intervention/forms/modalForms.py:345
 | 
			
		||||
msgid "Only recorded accounts can be selected for deductions"
 | 
			
		||||
msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden."
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:351
 | 
			
		||||
#: intervention/forms/modalForms.py:372
 | 
			
		||||
msgid "Only shared interventions can be selected"
 | 
			
		||||
msgstr "Nur freigegebene Eingriffe können gewählt werden"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:364
 | 
			
		||||
#: intervention/forms/modalForms.py:385
 | 
			
		||||
msgid "New Deduction"
 | 
			
		||||
msgstr "Neue Abbuchung"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:365
 | 
			
		||||
#: intervention/forms/modalForms.py:386
 | 
			
		||||
msgid "Enter the information for a new deduction from a chosen eco-account"
 | 
			
		||||
msgstr "Geben Sie die Informationen für eine neue Abbuchung ein."
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:408
 | 
			
		||||
#: intervention/forms/modalForms.py:429
 | 
			
		||||
msgid ""
 | 
			
		||||
"Eco-account {} is not recorded yet. You can only deduct from recorded "
 | 
			
		||||
"accounts."
 | 
			
		||||
@ -1407,7 +1419,7 @@ msgstr ""
 | 
			
		||||
"Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von "
 | 
			
		||||
"verzeichneten Ökokonten erfolgen."
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/modalForms.py:418
 | 
			
		||||
#: intervention/forms/modalForms.py:439
 | 
			
		||||
msgid ""
 | 
			
		||||
"The account {} has not enough surface for a deduction of {} m². There are "
 | 
			
		||||
"only {} m² left"
 | 
			
		||||
@ -2273,7 +2285,7 @@ msgstr "* sind Pflichtfelder."
 | 
			
		||||
msgid "New entry"
 | 
			
		||||
msgstr "Neuer Eintrag"
 | 
			
		||||
 | 
			
		||||
#: templates/generic_index.html:41 user/templates/user/team/index.html:23
 | 
			
		||||
#: templates/generic_index.html:41 user/templates/user/team/index.html:22
 | 
			
		||||
msgid "New"
 | 
			
		||||
msgstr "Neu"
 | 
			
		||||
 | 
			
		||||
@ -2406,7 +2418,7 @@ msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
 | 
			
		||||
msgid "Team name"
 | 
			
		||||
msgstr "Team Name"
 | 
			
		||||
 | 
			
		||||
#: user/forms.py:179 user/templates/user/team/index.html:31
 | 
			
		||||
#: user/forms.py:179 user/templates/user/team/index.html:30
 | 
			
		||||
msgid "Description"
 | 
			
		||||
msgstr "Beschreibung"
 | 
			
		||||
 | 
			
		||||
@ -2434,19 +2446,23 @@ msgstr ""
 | 
			
		||||
"Sie werden standardmäßig der Administrator dieses Teams. Sie müssen sich "
 | 
			
		||||
"selbst nicht zur Liste der Mitglieder hinzufügen."
 | 
			
		||||
 | 
			
		||||
#: user/forms.py:230
 | 
			
		||||
#: user/forms.py:218 user/forms.py:279
 | 
			
		||||
msgid "Name already taken. Try another."
 | 
			
		||||
msgstr "Name bereits vergeben. Probieren Sie einen anderen."
 | 
			
		||||
 | 
			
		||||
#: user/forms.py:249
 | 
			
		||||
msgid "Admin"
 | 
			
		||||
msgstr "Administrator"
 | 
			
		||||
 | 
			
		||||
#: user/forms.py:231
 | 
			
		||||
#: user/forms.py:250
 | 
			
		||||
msgid "Administrators manage team details and members"
 | 
			
		||||
msgstr "Administratoren verwalten die Teamdaten und Mitglieder"
 | 
			
		||||
 | 
			
		||||
#: user/forms.py:244
 | 
			
		||||
#: user/forms.py:263
 | 
			
		||||
msgid "Selected admin ({}) needs to be a member of this team."
 | 
			
		||||
msgstr "Gewählter Administrator ({}) muss ein Mitglied des Teams sein."
 | 
			
		||||
 | 
			
		||||
#: user/forms.py:256 user/templates/user/team/index.html:52
 | 
			
		||||
#: user/forms.py:291 user/templates/user/team/index.html:51
 | 
			
		||||
msgid "Edit team"
 | 
			
		||||
msgstr "Team bearbeiten"
 | 
			
		||||
 | 
			
		||||
@ -2466,7 +2482,7 @@ msgstr "Gelöscht"
 | 
			
		||||
msgid "Show contact data"
 | 
			
		||||
msgstr "Zeige Kontaktdaten"
 | 
			
		||||
 | 
			
		||||
#: user/templates/user/index.html:13 user/templates/user/team/index.html:30
 | 
			
		||||
#: user/templates/user/index.html:13 user/templates/user/team/index.html:29
 | 
			
		||||
msgid "Name"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
@ -2515,20 +2531,20 @@ msgstr ""
 | 
			
		||||
msgid "Manage teams"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: user/templates/user/index.html:69 user/templates/user/team/index.html:19
 | 
			
		||||
#: user/templates/user/index.html:69 user/templates/user/team/index.html:18
 | 
			
		||||
#: user/views.py:142
 | 
			
		||||
msgid "Teams"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: user/templates/user/team/index.html:21
 | 
			
		||||
#: user/templates/user/team/index.html:20
 | 
			
		||||
msgid "Add new team"
 | 
			
		||||
msgstr "Neues Team hinzufügen"
 | 
			
		||||
 | 
			
		||||
#: user/templates/user/team/index.html:32
 | 
			
		||||
#: user/templates/user/team/index.html:31
 | 
			
		||||
msgid "Members"
 | 
			
		||||
msgstr "Mitglieder"
 | 
			
		||||
 | 
			
		||||
#: user/templates/user/team/index.html:55
 | 
			
		||||
#: user/templates/user/team/index.html:54
 | 
			
		||||
msgid "Remove team"
 | 
			
		||||
msgstr "Team entfernen"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
from django.contrib import admin
 | 
			
		||||
 | 
			
		||||
from user.models import UserNotification, UserActionLogEntry, User
 | 
			
		||||
from user.models import UserNotification, UserActionLogEntry, User, Team
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserNotificationAdmin(admin.ModelAdmin):
 | 
			
		||||
@ -64,7 +64,20 @@ class UserActionLogEntryAdmin(admin.ModelAdmin):
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TeamAdmin(admin.ModelAdmin):
 | 
			
		||||
    list_display = [
 | 
			
		||||
        "name",
 | 
			
		||||
        "description",
 | 
			
		||||
        "admin",
 | 
			
		||||
    ]
 | 
			
		||||
    search_fields = [
 | 
			
		||||
        "name",
 | 
			
		||||
        "description",
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
admin.site.register(User, UserAdmin)
 | 
			
		||||
admin.site.register(Team, TeamAdmin)
 | 
			
		||||
 | 
			
		||||
# Outcommented for a cleaner admin backend on production
 | 
			
		||||
#admin.site.register(UserNotification, UserNotificationAdmin)
 | 
			
		||||
 | 
			
		||||
@ -206,6 +206,25 @@ class NewTeamModalForm(BaseModalForm):
 | 
			
		||||
        self.action_url = reverse("user:team-new")
 | 
			
		||||
        self.cancel_redirect = reverse("user:team-index")
 | 
			
		||||
 | 
			
		||||
    def _is_name_valid(self):
 | 
			
		||||
        name = self.cleaned_data.get("name", None)
 | 
			
		||||
        teams_with_same_name = Team.objects.filter(
 | 
			
		||||
            name=name
 | 
			
		||||
        )
 | 
			
		||||
        name_valid = not teams_with_same_name.exists()
 | 
			
		||||
        if not name_valid:
 | 
			
		||||
            self.add_error(
 | 
			
		||||
                "name",
 | 
			
		||||
                _("Name already taken. Try another.")
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        return name_valid
 | 
			
		||||
 | 
			
		||||
    def is_valid(self):
 | 
			
		||||
        super_valid = super().is_valid()
 | 
			
		||||
        name_valid = self._is_name_valid()
 | 
			
		||||
        return super_valid and name_valid
 | 
			
		||||
 | 
			
		||||
    def save(self):
 | 
			
		||||
        with transaction.atomic():
 | 
			
		||||
            team = Team.objects.create(
 | 
			
		||||
@ -246,6 +265,22 @@ class EditTeamModalForm(NewTeamModalForm):
 | 
			
		||||
 | 
			
		||||
        return _is_valid
 | 
			
		||||
 | 
			
		||||
    def _is_name_valid(self):
 | 
			
		||||
        name = self.cleaned_data.get("name", None)
 | 
			
		||||
        teams_with_same_name = Team.objects.filter(
 | 
			
		||||
            name=name
 | 
			
		||||
        ).exclude(
 | 
			
		||||
            id=self.instance.id
 | 
			
		||||
        )
 | 
			
		||||
        name_valid = not teams_with_same_name.exists()
 | 
			
		||||
        if not name_valid:
 | 
			
		||||
            self.add_error(
 | 
			
		||||
                "name",
 | 
			
		||||
                _("Name already taken. Try another.")
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        return name_valid
 | 
			
		||||
 | 
			
		||||
    def is_valid(self):
 | 
			
		||||
        super_valid = super().is_valid()
 | 
			
		||||
        admin_valid = self.__is_admin_valid()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user