def to_internal_value(self, data): if not data: return None try: actor = ActorTuple.from_actor_identifier(data) except Exception: raise serializers.ValidationError( "Could not parse actor. Format should be `type:id` where type is `team` or `user`." ) try: obj = actor.resolve() except (Team.DoesNotExist, User.DoesNotExist): raise serializers.ValidationError( f"{actor.type.__name__} does not exist") if actor.type == Team: if obj.organization != self.context["organization"]: raise serializers.ValidationError( "Team is not a member of this organization") elif actor.type == User: if not OrganizationMember.objects.filter( organization=self.context["organization"], user=obj).exists(): raise serializers.ValidationError( "User is not a member of this organization") return actor
def to_internal_value(self, data): if not data: return None try: return ActorTuple.from_actor_identifier(data) except Exception: raise serializers.ValidationError("Unknown actor input")
def validate_owner(self, owner): # owner should be team:id or user:id try: actor = ActorTuple.from_actor_identifier(owner) except serializers.ValidationError: raise serializers.ValidationError( "Could not parse owner. Format should be `type:id` where type is `team` or `user`." ) try: if actor.resolve(): return actor except (User.DoesNotExist, Team.DoesNotExist): raise serializers.ValidationError( "Could not resolve owner to existing team or user.")
def test_transfer_to_organization_alert_rules(self): from_org = self.create_organization() from_user = self.create_user() self.create_member(user=from_user, role="member", organization=from_org) team = self.create_team(organization=from_org) to_org = self.create_organization() to_team = self.create_team(organization=to_org) to_user = self.create_user() self.create_member(user=to_user, role="member", organization=to_org) project = self.create_project(teams=[team]) # should lose their owners alert_rule = self.create_alert_rule( organization=self.organization, projects=[project], owner=ActorTuple.from_actor_identifier(f"team:{team.id}"), ) rule1 = Rule.objects.create(label="another test rule", project=project, owner=team.actor) rule2 = Rule.objects.create(label="rule4", project=project, owner=from_user.actor) # should keep their owners rule3 = Rule.objects.create(label="rule2", project=project, owner=to_team.actor) rule4 = Rule.objects.create(label="rule3", project=project, owner=to_user.actor) project.transfer_to(organization=to_org) alert_rule.refresh_from_db() rule1.refresh_from_db() rule2.refresh_from_db() rule3.refresh_from_db() rule4.refresh_from_db() assert alert_rule.organization_id == to_org.id assert alert_rule.owner is None assert rule1.owner is None assert rule2.owner is None assert rule3.owner is not None assert rule4.owner is not None
def build_assigned_text(identity: Identity, assignee: str): actor = ActorTuple.from_actor_identifier(assignee) try: assigned_actor = actor.resolve() except actor.type.DoesNotExist: return if actor.type == Team: assignee_text = f"#{assigned_actor.slug}" elif actor.type == User: try: assignee_ident = Identity.objects.get( user=assigned_actor, idp__type="slack", idp__external_id=identity.idp.external_id ) assignee_text = f"<@{assignee_ident.external_id}>" except Identity.DoesNotExist: assignee_text = assigned_actor.get_display_name() else: raise NotImplementedError return f"*Issue assigned to {assignee_text} by <@{identity.external_id}>*"
def assigned_actor(self): from sentry.models import ActorTuple return ActorTuple.from_actor_identifier(self.assigned_actor_id())
def owner(self): from sentry.models import ActorTuple return ActorTuple.from_actor_identifier(self.owner_id())
def test_simple(self): project1 = self.create_project( teams=[self.team], slug="foo" ) # This project will return counts for this team user_owned_rule = self.create_alert_rule( organization=self.organization, projects=[project1], name="user owned rule", query="", aggregate="count()", time_window=1, threshold_type=AlertRuleThresholdType.ABOVE, resolve_threshold=10, threshold_period=1, owner=ActorTuple.from_actor_identifier(self.user.id), ) user_owned_incident = self.create_incident(status=20, alert_rule=user_owned_rule) activities = [] for i in range(1, 9): activities.append( IncidentActivity( incident=user_owned_incident, type=IncidentActivityType.CREATED.value, value=IncidentStatus.OPEN, date_added=before_now(days=i), ) ) IncidentActivity.objects.bulk_create(activities) self.login_as(user=self.user) response = self.get_success_response(self.team.organization.slug, self.team.slug) assert len(response.data) == 90 for i in range(1, 9): assert ( response.data[ str( before_now(days=i) .replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc) .isoformat() ) ] == 1 ) for i in range(10, 90): assert ( response.data[ str( before_now(days=i) .replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc) .isoformat() ) ] == 0 ) response = self.get_success_response( self.team.organization.slug, self.team.slug, statsPeriod="7d" ) assert len(response.data) == 7 assert ( response.data[ str( before_now(days=0) .replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc) .isoformat() ) ] == 0 ) for i in range(1, 6): assert ( response.data[ str( before_now(days=i) .replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc) .isoformat() ) ] == 1 )
def test_not_as_simple(self): team_with_user = self.create_team( organization=self.organization, name="Lonely Team", members=[self.user] ) project1 = self.create_project( teams=[self.team], slug="foo" ) # This project will return counts for this team project2 = self.create_project( # teams=[team_with_user], slug="bar" teams=[team_with_user], slug="bar", ) # but not this project, cause this team isn't on it (but the user is) user_owned_rule = self.create_alert_rule( organization=self.organization, projects=[project2], name="user owned rule", query="", aggregate="count()", time_window=1, threshold_type=AlertRuleThresholdType.ABOVE, resolve_threshold=10, threshold_period=1, owner=ActorTuple.from_actor_identifier(self.user.id), ) user_owned_incident = self.create_incident( projects=[project2], status=20, alert_rule=user_owned_rule ) team_owned_rule = self.create_alert_rule( organization=self.organization, projects=[project1], name="team owned rule", query="", aggregate="count()", time_window=1, threshold_type=AlertRuleThresholdType.ABOVE, resolve_threshold=10, threshold_period=1, owner=ActorTuple.from_actor_identifier(f"team:{self.team.id}"), ) team_owned_incident = self.create_incident( projects=[project1], status=20, alert_rule=team_owned_rule ) IncidentActivity.objects.create( incident=user_owned_incident, type=IncidentActivityType.CREATED.value, value=IncidentStatus.OPEN, ) IncidentActivity.objects.create( incident=team_owned_incident, type=IncidentActivityType.CREATED.value, value=IncidentStatus.OPEN, date_added=before_now(days=2), ) self.login_as(user=self.user) response = self.get_success_response(self.team.organization.slug, self.team.slug) assert len(response.data) == 90 assert ( response.data[ str( before_now(days=2) .replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc) .isoformat() ) ] == 1 ) # only getting the team owned incident, because the user owned incident is for another project that the team isn't on for i in range(0, 90): if i != 2: assert ( response.data[ str( before_now(days=i) .replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=timezone.utc) .isoformat() ) ] == 0 )
def test(self): project1 = self.create_project(teams=[self.team], slug="foo") user_owned_rule = self.create_alert_rule( organization=self.organization, projects=[project1], name="user owned rule", owner=ActorTuple.from_actor_identifier(self.user.id), ) user_owned_incident = self.create_incident(status=20, alert_rule=user_owned_rule) activities = [] for i in range(0, 8): activities.append( IncidentActivity( incident=user_owned_incident, type=IncidentActivityType.CREATED.value, value=IncidentStatus.OPEN, date_added=before_now(weeks=i), ) ) team_owned_rule = self.create_alert_rule( organization=self.organization, projects=[project1], name="team owned rule", owner=ActorTuple.from_actor_identifier(f"team:{self.team.id}"), ) team_owned_incident = self.create_incident(status=20, alert_rule=team_owned_rule) activities.append( IncidentActivity( incident=team_owned_incident, type=IncidentActivityType.CREATED.value, value=IncidentStatus.OPEN, date_added=before_now(weeks=0), ) ) for i in range(0, 10): activities.append( IncidentActivity( incident=team_owned_incident, type=IncidentActivityType.CREATED.value, value=IncidentStatus.OPEN, date_added=before_now(weeks=i), ) ) IncidentActivity.objects.bulk_create(activities) self.login_as(user=self.user) response = self.get_success_response( self.team.organization.slug, self.team.slug, statsPeriod="8w" ) assert [ {"id": row["id"], "totalThisWeek": row["totalThisWeek"], "weeklyAvg": row["weeklyAvg"]} for row in response.data ] == [ {"id": str(team_owned_rule.id), "totalThisWeek": 2, "weeklyAvg": 1.375}, {"id": str(user_owned_rule.id), "totalThisWeek": 1, "weeklyAvg": 1}, ] response = self.get_success_response( self.team.organization.slug, self.team.slug, per_page=1, statsPeriod="10w" ) assert [ {"id": row["id"], "totalThisWeek": row["totalThisWeek"], "weeklyAvg": row["weeklyAvg"]} for row in response.data ] == [ {"id": str(team_owned_rule.id), "totalThisWeek": 2, "weeklyAvg": 1.1}, ] next_cursor = self.get_cursor_headers(response)[1] response = self.get_success_response( self.team.organization.slug, self.team.slug, per_page=1, cursor=next_cursor, statsPeriod="10w", ) assert [ {"id": row["id"], "totalThisWeek": row["totalThisWeek"], "weeklyAvg": row["weeklyAvg"]} for row in response.data ] == [ {"id": str(user_owned_rule.id), "totalThisWeek": 1, "weeklyAvg": 0.8}, ]