Example #1
0
    def test_team_actors_to_user_ids(self):
        team1 = self.create_team()
        team2 = self.create_team()
        team3 = self.create_team()  # team with no active members
        users = [self.create_user() for i in range(0, 8)]

        self.create_member(user=users[0], organization=self.organization, teams=[team1])
        self.create_member(user=users[1], organization=self.organization, teams=[team1])
        self.create_member(user=users[2], organization=self.organization, teams=[team1])
        self.create_member(user=users[3], organization=self.organization, teams=[team1, team2])
        self.create_member(user=users[4], organization=self.organization, teams=[team2, self.team])
        self.create_member(user=users[5], organization=self.organization, teams=[team2])

        # Inactive member
        member6 = self.create_member(
            user=users[6],
            organization=self.organization,
            teams=[
                team2,
                team3])
        team_member6 = OrganizationMemberTeam.objects.filter(organizationmember_id=member6.id)
        for team_member in team_member6:
            team_member.update(is_active=False)
        # Member without teams
        self.create_member(user=users[7], organization=self.organization, teams=[])

        team_actors = [Actor(team1.id, Team), Actor(team2.id, Team), Actor(team3.id, Team)]
        user_ids = [user.id for user in users]

        assert team_actors_to_user_ids(team_actors, user_ids) == {
            team1.id: set([users[0].id, users[1].id, users[2].id, users[3].id]),
            team2.id: set([users[3].id, users[4].id, users[5].id]),
        }
Example #2
0
def resolve_actor(owner, project_id):
    """ Convert an Owner object into an Actor """
    from sentry.api.fields.actor import Actor
    from sentry.models import User, Team

    if owner.type == 'user':
        try:
            user_id = User.objects.filter(
                email__iexact=owner.identifier,
                is_active=True,
                sentry_orgmember_set__organizationmemberteam__team__projectteam__project_id=project_id,
            ).values_list('id', flat=True)[0]
        except IndexError:
            raise UnknownActor

        return Actor(user_id, User)

    if owner.type == 'team':
        try:
            team_id = Team.objects.filter(
                projectteam__project_id=project_id,
                slug=owner.identifier,
            ).values_list('id', flat=True)[0]
        except IndexError:
            return UnknownActor

        return Actor(team_id, Team)

    raise TypeError('Unknown actor type: %r' % owner.type)
 def test_basic(self):
     owners = [
         Owner("user", self.user.email),
         Owner("team", self.team.slug)
     ]
     assert resolve_actors(owners, self.project.id) == {
         owners[0]: Actor(self.user.id, User),
         owners[1]: Actor(self.team.id, Team),
     }
Example #4
0
    def test_build_events_by_actor(self):
        events = self.team1_events + self.team2_events + self.user4_events

        events_by_actor = {
            Actor(self.team1.id, Team): set(self.team1_events),
            Actor(self.team2.id, Team): set(self.team2_events),
            Actor(self.user3.id, User): set(self.team1_events),
            Actor(self.user4.id, User): set(self.user4_events),
        }
        assert build_events_by_actor(self.project.id, events, self.user_ids) == events_by_actor
Example #5
0
    def test_users(self):
        actor = Actor(self.user.id, User)
        result = extract_user_ids_from_mentions(self.organization.id, [actor])
        assert result['users'] == set([self.user.id])
        assert result['team_users'] == set()

        other_user = self.create_user()
        result = extract_user_ids_from_mentions(
            self.organization.id, [actor, Actor(other_user.id, User)])
        assert result['users'] == set([self.user.id, other_user.id])
        assert result['team_users'] == set()
Example #6
0
    def test_convert_actors_to_user_set(self):
        user1 = self.create_user()
        user2 = self.create_user()
        user3 = self.create_user()
        user4 = self.create_user()

        team1 = self.create_team()
        team2 = self.create_team()

        self.create_member(user=user1,
                           organization=self.organization,
                           teams=[team1])
        self.create_member(user=user2,
                           organization=self.organization,
                           teams=[team2])
        self.create_member(user=user3,
                           organization=self.organization,
                           teams=[team1, team2])
        self.create_member(user=user4,
                           organization=self.organization,
                           teams=[])

        team1_events = set([
            self.create_event(self.project.id),
            self.create_event(self.project.id),
            self.create_event(self.project.id),
            self.create_event(self.project.id),
        ])
        team2_events = set([
            self.create_event(self.project.id),
            self.create_event(self.project.id),
            self.create_event(self.project.id),
            self.create_event(self.project.id),
        ])
        user4_events = set([
            self.create_event(self.project.id),
            self.create_event(self.project.id)
        ])
        events_by_actor = {
            Actor(team1.id, Team): team1_events,
            Actor(team2.id, Team): team2_events,
            Actor(user3.id, User): team1_events.union(team2_events),
            Actor(user4.id, User): user4_events,
        }
        user_by_events = {
            user1.id: team1_events,
            user2.id: team2_events,
            user3.id: team1_events.union(team2_events),
            user4.id: user4_events,
        }
        assert convert_actors_to_users(events_by_actor,
                                       user_by_events.keys()) == user_by_events
Example #7
0
def resolve_actors(owners, project_id):
    """ Convert a list of Owner objects into a dictionary
    of {Owner: Actor} pairs. Actors not identified are returned
    as None. """
    from sentry.api.fields.actor import Actor
    from sentry.models import User, Team

    if not owners:
        return {}

    users, teams = [], []
    owners_lookup = {}

    for owner in owners:
        # teams aren't technical case insensitive, but teams also
        # aren't allowed to have non-lowercase in slugs, so
        # this kinda works itself out correctly since they won't match
        owners_lookup[(owner.type, owner.identifier.lower())] = owner
        if owner.type == 'user':
            users.append(owner)
        elif owner.type == 'team':
            teams.append(owner)

    actors = {}
    if users:
        actors.update({
            ('user', email.lower()): Actor(u_id, User)
            for u_id, email in User.objects.filter(
                reduce(
                    operator.or_,
                    [Q(emails__email__iexact=o.identifier) for o in users]
                ),
                # We don't require verified emails
                # emails__is_verified=True,
                is_active=True,
                sentry_orgmember_set__organizationmemberteam__team__projectteam__project_id=project_id,
            ).distinct().values_list('id', 'emails__email')
        })

    if teams:
        actors.update({
            ('team', slug): Actor(t_id, Team)
            for t_id, slug in Team.objects.filter(
                slug__in=[o.identifier for o in teams],
                projectteam__project_id=project_id,
            ).values_list('id', 'slug')
        })

    return {
        o: actors.get((o.type, o.identifier.lower()))
        for o in owners
    }
Example #8
0
    def test_teams(self):
        member_user = self.create_user()
        self.create_member(user=member_user,
                           organization=self.organization,
                           role="member",
                           teams=[self.team])
        actor = Actor(self.team.id, Team)
        result = extract_user_ids_from_mentions(self.organization.id, [actor])
        assert result["users"] == set()
        assert result["team_users"] == set([self.user.id, member_user.id])

        # Explicitly mentioned users shouldn't be included in team_users
        result = extract_user_ids_from_mentions(
            self.organization.id, [Actor(member_user.id, User), actor])
        assert result["users"] == set([member_user.id])
        assert result["team_users"] == set([self.user.id])
Example #9
0
    def test_get_owners_basic(self):
        matcher = Matcher('path', '*.py')

        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([
                Rule(matcher, [
                    Owner('user', self.user.email),
                    Owner('team', self.team.slug),
                ]),
            ]),
            fallthrough=True,
        )

        # No data matches
        assert ProjectOwnership.get_owners(self.project.id,
                                           {}) == (ProjectOwnership.Everyone,
                                                   None)

        assert ProjectOwnership.get_owners(self.project.id, {
            'sentry.interfaces.Stacktrace': {
                'frames': [{
                    'filename': 'foo.py',
                }]
            }
        }) == ([Actor(self.user.id, User),
                Actor(self.team.id, Team)], matcher)

        assert ProjectOwnership.get_owners(self.project.id, {
            'sentry.interfaces.Stacktrace': {
                'frames': [{
                    'filename': 'xxxx',
                }]
            }
        }) == (ProjectOwnership.Everyone, None)

        # When fallthrough = False, we don't implicitly assign to Everyone
        ProjectOwnership.objects.filter(
            project_id=self.project.id, ).update(fallthrough=False)

        assert ProjectOwnership.get_owners(self.project.id, {
            'sentry.interfaces.Stacktrace': {
                'frames': [{
                    'filename': 'xxxx',
                }]
            }
        }) == ([], None)
Example #10
0
    def test_team(self):
        data = {
            'actor_field': "team:1",
        }

        serializer = DummySerializer(data=data)
        assert serializer.is_valid()
        assert serializer.object == {'actor_field': Actor(id=1, type=Team)}
Example #11
0
    def test_simple(self):
        data = {
            'actor_field': "user:1",
        }

        serializer = DummySerializer(data=data)
        assert serializer.is_valid()
        assert serializer.object == {'actor_field': Actor(id=1, type=User)}
Example #12
0
    def test_legacy_user_fallback(self):
        data = {
            'actor_field': "1",
        }

        serializer = DummySerializer(data=data)
        assert serializer.is_valid()
        assert serializer.object == {'actor_field': Actor(id=1, type=User)}
    def test_get_owners_basic(self):
        rule_a = Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)])

        rule_b = Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)])

        ProjectOwnership.objects.create(
            project_id=self.project.id, schema=dump_schema([rule_a, rule_b]), fallthrough=True
        )

        # No data matches
        assert ProjectOwnership.get_owners(self.project.id, {}) == (ProjectOwnership.Everyone, None)

        # Match only rule_a
        self.assert_ownership_equals(
            ProjectOwnership.get_owners(
                self.project.id, {"stacktrace": {"frames": [{"filename": "foo.py"}]}}
            ),
            ([Actor(self.team.id, Team)], [rule_a]),
        )

        # Match only rule_b
        self.assert_ownership_equals(
            ProjectOwnership.get_owners(
                self.project.id, {"stacktrace": {"frames": [{"filename": "src/thing.txt"}]}}
            ),
            ([Actor(self.user.id, User)], [rule_b]),
        )

        # Matches both rule_a and rule_b
        self.assert_ownership_equals(
            ProjectOwnership.get_owners(
                self.project.id, {"stacktrace": {"frames": [{"filename": "src/foo.py"}]}}
            ),
            ([Actor(self.user.id, User), Actor(self.team.id, Team)], [rule_a, rule_b]),
        )

        assert ProjectOwnership.get_owners(
            self.project.id, {"stacktrace": {"frames": [{"filename": "xxxx"}]}}
        ) == (ProjectOwnership.Everyone, None)

        # When fallthrough = False, we don't implicitly assign to Everyone
        ProjectOwnership.objects.filter(project_id=self.project.id).update(fallthrough=False)

        assert ProjectOwnership.get_owners(
            self.project.id, {"stacktrace": {"frames": [{"filename": "xxxx"}]}}
        ) == ([], None)
Example #14
0
def resolve_actors(owners, project_id):
    """ Convert a list of Owner objects into a dictionary
    of {Owner: Actor} pairs. Actors not identified are returned
    as None. """
    from sentry.api.fields.actor import Actor
    from sentry.ownership.grammar import Owner
    from sentry.models import User, Team

    if not owners:
        return {}

    users, teams = [], []

    owners_to_actors = {o: None for o in owners}

    for owner in owners:
        if owner.type == 'user':
            users.append(owner)
        elif owner.type == 'team':
            teams.append(owner)

    actors = []
    if users:
        actors.extend([(
            'user', email, Actor(u_id, User)
        ) for u_id, email in User.objects.filter(
            reduce(operator.or_,
                   [Q(email__iexact=o.identifier) for o in users]),
            is_active=True,
            sentry_orgmember_set__organizationmemberteam__team__projectteam__project_id
            =project_id,
        ).values_list('id', 'email')])

    if teams:
        actors.extend([('team', slug, Actor(t_id, Team))
                       for t_id, slug in Team.objects.filter(
                           slug__in=[o.identifier for o in teams],
                           projectteam__project_id=project_id,
                       ).values_list('id', 'slug')])

    for type, identifier, actor in actors:
        owners_to_actors[Owner(type, identifier)] = actor

    return owners_to_actors
Example #15
0
def build_events_by_actor(project_id, events, user_ids):
    """
    build_events_by_actor(project_id: Int, events: Set(Events), user_ids: Set[Int]) -> Map[Actor, Set(Events)]
    """
    events_by_actor = defaultdict(set)
    for event in events:
        # TODO(LB): I Know this is inefficient.
        # ProjectOwnership.get_owners is O(n) queries and I'm doing that O(len(events)) times
        # I will create a follow-up PR to address this method's efficiency problem
        # Just wanted to make as few changes as possible for now.
        actors, __ = ProjectOwnership.get_owners(project_id, event.data)
        if actors == ProjectOwnership.Everyone:
            actors = [Actor(user_id, User) for user_id in user_ids]
        for actor in actors:
            events_by_actor[actor].add(event)
    return events_by_actor
Example #16
0
    def test_teams(self):
        # Normal team
        owner1 = Owner('team', self.team.slug)
        actor1 = Actor(self.team.id, Team)

        # Team that doesn't exist
        owner2 = Owner('team', 'nope')
        actor2 = None

        # A team that's not ours
        otherteam = Team.objects.exclude(projectteam__project_id=self.project.id)[0]
        owner3 = Owner('team', otherteam.slug)
        actor3 = None

        assert resolve_actors([owner1, owner2, owner3], self.project.id) == {
            owner1: actor1,
            owner2: actor2,
            owner3: actor3,
        }
    def test_users(self):
        # Normal user
        owner1 = Owner("user", self.user.email)
        actor1 = Actor(self.user.id, User)

        # An extra secondary email
        email1 = self.create_useremail(self.user, None, is_verified=True).email
        owner2 = Owner("user", email1)
        actor2 = actor1  # They map to the same user since it's just a secondary email

        # Another secondary email, that isn't verified
        email2 = self.create_useremail(self.user, None,
                                       is_verified=False).email
        owner3 = Owner("user", email2)
        # Intentionally allow unverified emails
        # actor3 = None
        actor3 = actor1

        # An entirely unknown user
        owner4 = Owner("user", "nope")
        actor4 = None

        # A user that doesn't belong with us
        otheruser = self.create_user()
        owner5 = Owner("user", otheruser.email)
        actor5 = None

        # Case-insensitive for user
        owner6 = Owner("user", self.user.email.upper())
        actor6 = actor1

        assert resolve_actors([owner1, owner2, owner3, owner4, owner5, owner6],
                              self.project.id) == {
                                  owner1: actor1,
                                  owner2: actor2,
                                  owner3: actor3,
                                  owner4: actor4,
                                  owner5: actor5,
                                  owner6: actor6,
                              }
Example #18
0
    def test_get_owners_basic(self):
        rule_a = Rule(
            Matcher('path', '*.py'), [
                Owner('team', self.team.slug),
            ])

        rule_b = Rule(
            Matcher('path', 'src/*'), [
                Owner('user', self.user.email),
            ])

        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([rule_a, rule_b]),
            fallthrough=True,
        )

        # No data matches
        assert ProjectOwnership.get_owners(self.project.id, {}) == (ProjectOwnership.Everyone, None)

        # Match only rule_a
        self.assert_ownership_equals(ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'foo.py',
                    }]
                }
            }
        ), ([Actor(self.team.id, Team)], [rule_a]))

        # Match only rule_b
        self.assert_ownership_equals(ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'src/thing.txt',
                    }]
                }
            }
        ), ([Actor(self.user.id, User)], [rule_b]))

        # Matches both rule_a and rule_b
        self.assert_ownership_equals(ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'src/foo.py',
                    }]
                }
            }
        ), ([Actor(self.user.id, User), Actor(self.team.id, Team)], [rule_a, rule_b]))

        assert ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'xxxx',
                    }]
                }
            }
        ) == (ProjectOwnership.Everyone, None)

        # When fallthrough = False, we don't implicitly assign to Everyone
        ProjectOwnership.objects.filter(
            project_id=self.project.id,
        ).update(fallthrough=False)

        assert ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'xxxx',
                    }]
                }
            }
        ) == ([], None)