|
4 | 4 | from rest_framework.exceptions import ErrorDetail |
5 | 5 | from rest_framework.serializers import ValidationError |
6 | 6 |
|
| 7 | +from sentry.auth.access import SystemAccess |
7 | 8 | from sentry.notifications.models.notificationaction import ActionTarget |
8 | 9 | from sentry.testutils.cases import TestCase |
| 10 | +from sentry.types.actor import Actor |
9 | 11 | from sentry.workflow_engine.endpoints.serializers.workflow_serializer import ( |
10 | 12 | TriggerSerializerResponse, |
11 | 13 | WorkflowSerializer, |
@@ -154,6 +156,89 @@ def test_create__simple(self) -> None: |
154 | 156 | assert workflow.organization_id == self.organization.id |
155 | 157 | assert workflow.created_by_id == self.user.id |
156 | 158 |
|
| 159 | + def test_create__owner_user_id(self) -> None: |
| 160 | + self.valid_data["owner"] = f"user:{self.user.id}" |
| 161 | + validator = WorkflowValidator(data=self.valid_data, context=self.context) |
| 162 | + assert validator.is_valid() is True |
| 163 | + workflow = validator.create(validator.validated_data) |
| 164 | + workflow.refresh_from_db() |
| 165 | + assert workflow.owner_user_id == self.user.id |
| 166 | + |
| 167 | + def test_team_owner(self) -> None: |
| 168 | + team = self.create_team(organization=self.organization, members=[self.user]) |
| 169 | + self.valid_data["owner"] = f"team:{team.id}" |
| 170 | + validator = WorkflowValidator(data=self.valid_data, context=self.context) |
| 171 | + assert validator.is_valid() is True |
| 172 | + workflow = validator.create(validator.validated_data) |
| 173 | + workflow.refresh_from_db() |
| 174 | + assert workflow.owner_team_id == team.id |
| 175 | + assert workflow.owner_user_id is None |
| 176 | + |
| 177 | + def test_owner_perms(self) -> None: |
| 178 | + other_user = self.create_user() |
| 179 | + self.valid_data["owner"] = f"user:{other_user.id}" |
| 180 | + validator = WorkflowValidator(data=self.valid_data, context=self.context) |
| 181 | + assert validator.is_valid() is False |
| 182 | + assert str(validator.errors["owner"][0]) == "User is not a member of this organization" |
| 183 | + |
| 184 | + other_team = self.create_team(self.create_organization()) |
| 185 | + self.valid_data["owner"] = f"team:{other_team.id}" |
| 186 | + validator = WorkflowValidator(data=self.valid_data, context=self.context) |
| 187 | + assert validator.is_valid() is False |
| 188 | + assert str(validator.errors["owner"][0]) == "Team is not a member of this organization" |
| 189 | + |
| 190 | + def test_team_owner_not_member(self) -> None: |
| 191 | + self.organization.flags.allow_joinleave = False |
| 192 | + self.organization.save() |
| 193 | + |
| 194 | + team = self.create_team(organization=self.organization) |
| 195 | + member_user = self.create_user() |
| 196 | + self.create_member( |
| 197 | + user=member_user, |
| 198 | + organization=self.organization, |
| 199 | + role="member", |
| 200 | + teams=[self.team], |
| 201 | + ) |
| 202 | + |
| 203 | + context = { |
| 204 | + "organization": self.organization, |
| 205 | + "request": self.make_request(user=member_user), |
| 206 | + } |
| 207 | + self.valid_data["owner"] = f"team:{team.id}" |
| 208 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 209 | + assert validator.is_valid() is False |
| 210 | + assert str(validator.errors["owner"][0]) == "You can only assign teams you are a member of" |
| 211 | + |
| 212 | + def test_team_owner_not_member_with_team_admin_scope(self) -> None: |
| 213 | + team = self.create_team(organization=self.organization) |
| 214 | + |
| 215 | + context = { |
| 216 | + "organization": self.organization, |
| 217 | + "request": self.make_request(user=self.user), |
| 218 | + "access": SystemAccess(), |
| 219 | + } |
| 220 | + self.valid_data["owner"] = f"team:{team.id}" |
| 221 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 222 | + assert validator.is_valid() is True |
| 223 | + workflow = validator.create(validator.validated_data) |
| 224 | + assert workflow.owner_team_id == team.id |
| 225 | + assert workflow.owner_user_id is None |
| 226 | + |
| 227 | + def test_user_owner_another_member(self) -> None: |
| 228 | + other_user = self.create_user() |
| 229 | + self.create_member( |
| 230 | + user=other_user, |
| 231 | + organization=self.organization, |
| 232 | + role="member", |
| 233 | + ) |
| 234 | + |
| 235 | + self.valid_data["owner"] = f"user:{other_user.id}" |
| 236 | + validator = WorkflowValidator(data=self.valid_data, context=self.context) |
| 237 | + assert validator.is_valid() is True |
| 238 | + workflow = validator.create(validator.validated_data) |
| 239 | + assert workflow.owner_user_id == other_user.id |
| 240 | + assert workflow.owner_team_id is None |
| 241 | + |
157 | 242 | def test_create__validate_triggers_empty(self) -> None: |
158 | 243 | validator = WorkflowValidator(data=self.valid_data, context=self.context) |
159 | 244 | assert validator.is_valid() is True |
@@ -732,3 +817,116 @@ def test_update__remove_all_actions(self, mock_action_validator: mock.MagicMock) |
732 | 817 | workflow_condition_group = self.workflow.workflowdataconditiongroup_set.first() |
733 | 818 | assert workflow_condition_group is not None |
734 | 819 | assert workflow_condition_group.condition_group.dataconditiongroupaction_set.count() == 0 |
| 820 | + |
| 821 | + def test_update_owner_type(self, mock_action_validator: mock.MagicMock) -> None: |
| 822 | + team = self.create_team(organization=self.organization, members=[self.user]) |
| 823 | + context = {**self.context, "request": self.make_request(user=self.user)} |
| 824 | + |
| 825 | + self.valid_data["owner"] = f"team:{team.id}" |
| 826 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 827 | + assert validator.is_valid() is True |
| 828 | + workflow = validator.update(self.workflow, validator.validated_data) |
| 829 | + workflow.refresh_from_db() |
| 830 | + assert workflow.owner_team_id == team.id |
| 831 | + assert workflow.owner_user_id is None |
| 832 | + |
| 833 | + self.valid_data["owner"] = f"user:{self.user.id}" |
| 834 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 835 | + assert validator.is_valid() is True |
| 836 | + workflow.refresh_from_db() |
| 837 | + workflow = validator.update(self.workflow, validator.validated_data) |
| 838 | + assert workflow.owner_user_id == self.user.id |
| 839 | + assert workflow.owner_team_id is None |
| 840 | + |
| 841 | + def test_team_owner_not_member(self, mock_action_validator: mock.MagicMock) -> None: |
| 842 | + self.organization.flags.allow_joinleave = False |
| 843 | + self.organization.save() |
| 844 | + |
| 845 | + team = self.create_team(organization=self.organization) |
| 846 | + member_user = self.create_user() |
| 847 | + self.create_member( |
| 848 | + user=member_user, |
| 849 | + organization=self.organization, |
| 850 | + role="member", |
| 851 | + teams=[self.team], |
| 852 | + ) |
| 853 | + |
| 854 | + context = {**self.context, "request": self.make_request(user=member_user)} |
| 855 | + self.valid_data["owner"] = f"team:{team.id}" |
| 856 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 857 | + assert validator.is_valid() is False |
| 858 | + assert str(validator.errors["owner"][0]) == "You can only assign teams you are a member of" |
| 859 | + |
| 860 | + def test_team_owner_not_member_with_team_admin_scope( |
| 861 | + self, mock_action_validator: mock.MagicMock |
| 862 | + ) -> None: |
| 863 | + team = self.create_team(organization=self.organization) |
| 864 | + |
| 865 | + context = {**self.context, "access": SystemAccess()} |
| 866 | + self.valid_data["owner"] = f"team:{team.id}" |
| 867 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 868 | + assert validator.is_valid() is True |
| 869 | + workflow = validator.update(self.workflow, validator.validated_data) |
| 870 | + assert workflow.owner_team_id == team.id |
| 871 | + assert workflow.owner_user_id is None |
| 872 | + |
| 873 | + def test_reassign_owner_from_own_team_to_any_team( |
| 874 | + self, mock_action_validator: mock.MagicMock |
| 875 | + ) -> None: |
| 876 | + member_team = self.create_team(organization=self.organization) |
| 877 | + member_user = self.create_user() |
| 878 | + self.create_member( |
| 879 | + user=member_user, |
| 880 | + organization=self.organization, |
| 881 | + role="member", |
| 882 | + teams=[member_team], |
| 883 | + ) |
| 884 | + target_team = self.create_team(organization=self.organization) |
| 885 | + |
| 886 | + self.workflow.owner_team_id = member_team.id |
| 887 | + self.workflow.save() |
| 888 | + |
| 889 | + current_owner = Actor.from_id(user_id=None, team_id=member_team.id) |
| 890 | + context = { |
| 891 | + **self.context, |
| 892 | + "request": self.make_request(user=member_user), |
| 893 | + "current_owner": current_owner, |
| 894 | + } |
| 895 | + self.valid_data["owner"] = f"team:{target_team.id}" |
| 896 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 897 | + assert validator.is_valid() is True |
| 898 | + workflow = validator.update(self.workflow, validator.validated_data) |
| 899 | + assert workflow.owner_team_id == target_team.id |
| 900 | + |
| 901 | + def test_cannot_reassign_owner_from_other_team( |
| 902 | + self, mock_action_validator: mock.MagicMock |
| 903 | + ) -> None: |
| 904 | + self.organization.flags.allow_joinleave = False |
| 905 | + self.organization.save() |
| 906 | + |
| 907 | + other_team = self.create_team(organization=self.organization) |
| 908 | + member_team = self.create_team(organization=self.organization) |
| 909 | + member_user = self.create_user() |
| 910 | + self.create_member( |
| 911 | + user=member_user, |
| 912 | + organization=self.organization, |
| 913 | + role="member", |
| 914 | + teams=[member_team], |
| 915 | + ) |
| 916 | + target_team = self.create_team(organization=self.organization) |
| 917 | + |
| 918 | + self.workflow.owner_team_id = other_team.id |
| 919 | + self.workflow.save() |
| 920 | + |
| 921 | + current_owner = Actor.from_id(user_id=None, team_id=other_team.id) |
| 922 | + context = { |
| 923 | + **self.context, |
| 924 | + "request": self.make_request(user=member_user), |
| 925 | + "current_owner": current_owner, |
| 926 | + } |
| 927 | + self.valid_data["owner"] = f"team:{target_team.id}" |
| 928 | + validator = WorkflowValidator(data=self.valid_data, context=context) |
| 929 | + assert validator.is_valid() is False |
| 930 | + assert str(validator.errors["owner"][0]) == "You can only assign teams you are a member of" |
| 931 | + self.workflow.refresh_from_db() |
| 932 | + assert self.workflow.owner_team_id == other_team.id |
0 commit comments