def get(self, request, project, event_id): """ Retrieve suggested owners information for an event `````````````````````````````````````````````````` :pparam string project_slug: the slug of the project the event belongs to. :pparam string event_id: the id of the event. :auth: required """ try: event = Event.objects.get( id=event_id, project_id=project.id, ) except Event.DoesNotExist: return Response({'detail': 'Event not found'}, status=404) # populate event data Event.objects.bind_nodes([event], 'data') owners = ProjectOwnership.get_owners(project.id, event.data) # For sake of the API, we don't differentiate between # the implicit "everyone" and no owners if owners == ProjectOwnership.Everyone: owners = [] return Response( serialize( Actor.resolve_many(owners), request.user, ActorSerializer(), ))
def extract_user_ids_from_mentions(organization_id, mentions): """ Extracts user ids from a set of mentions. Mentions should be a list of `Actor` instances. Returns a dictionary with 'users' and 'team_users' keys. 'users' is the user ids for all explicitly mentioned users, and 'team_users' is all user ids from explicitly mentioned teams, excluding any already mentioned users. """ actors = Actor.resolve_many(mentions) actor_mentions = seperate_resolved_actors(actors) mentioned_team_users = list( User.objects.get_from_teams( organization_id, actor_mentions['teams'], ).exclude(id__in={u.id for u in actor_mentions['users']}).values_list( 'id', flat=True, ) ) return { 'users': set([user.id for user in actor_mentions['users']]), 'team_users': set(mentioned_team_users), }
def get_autoassign_owners(cls, project_id, data, limit=2): """ Get the auto-assign owner for a project if there are any. Returns a tuple of (auto_assignment_enabled, list_of_owners). """ with metrics.timer("projectownership.get_autoassign_owners"): ownership = cls.get_ownership_cached(project_id) if not ownership: return False, [] rules = cls._matching_ownership_rules(ownership, project_id, data) if not rules: return ownership.auto_assignment, [] # We want the last matching rule to take the most precedence. owners = [owner for rule in rules for owner in rule.owners] owners.reverse() actors = { key: val for key, val in resolve_actors({owner for owner in owners}, project_id).items() if val } actors = [actors[owner] for owner in owners if owner in actors][:limit] # Can happen if the ownership rule references a user/team that no longer # is assigned to the project or has been removed from the org. if not actors: return ownership.auto_assignment, [] from sentry.api.fields.actor import Actor return ownership.auto_assignment, Actor.resolve_many(actors)
def get(self, request, project, event_id): """ Retrieve suggested owners information for an event `````````````````````````````````````````````````` :pparam string project_slug: the slug of the project the event belongs to. :pparam string event_id: the id of the event. :auth: required """ event = eventstore.get_event_by_id(project.id, event_id) if event is None: return Response({"detail": "Event not found"}, status=404) # populate event data Event.objects.bind_nodes([event], "data") owners, rules = ProjectOwnership.get_owners(project.id, event.data) # For sake of the API, we don't differentiate between # the implicit "everyone" and no owners if owners == ProjectOwnership.Everyone: owners = [] return Response({ "owners": serialize(Actor.resolve_many(owners), request.user, ActorSerializer()), # TODO(mattrobenolt): We need to change the API here to return # all rules, just keeping this way currently for API compat "rule": rules[0].matcher if rules else None, "rules": rules or [], })
def get(self, request, project, event_id): """ Retrieve suggested owners information for an event `````````````````````````````````````````````````` :pparam string project_slug: the slug of the project the event belongs to. :pparam string event_id: the id of the event. :auth: required """ event = eventstore.get_event_by_id(project.id, event_id) if event is None: return Response({"detail": "Event not found"}, status=404) # populate event data if not options.get("eventstore.use-nodestore"): event.bind_node_data() owners, rules = ProjectOwnership.get_owners(project.id, event.data) # For sake of the API, we don't differentiate between # the implicit "everyone" and no owners if owners == ProjectOwnership.Everyone: owners = [] serialized_owners = serialize(Actor.resolve_many(owners), request.user, ActorSerializer()) # Make sure the serialized owners are in the correct order ordered_owners = [] owner_by_id = {(o["id"], o["type"]): o for o in serialized_owners} for o in owners: key = (six.text_type(o.id), "team" if o.type == Team else "user") if owner_by_id.get(key): ordered_owners.append(owner_by_id[key]) return Response({ "owners": ordered_owners, # TODO(mattrobenolt): We need to change the API here to return # all rules, just keeping this way currently for API compat "rule": rules[0].matcher if rules else None, "rules": rules or [], })
def get(self, request, project, event_id): """ Retrieve suggested owners information for an event `````````````````````````````````````````````````` :pparam string project_slug: the slug of the project the event belongs to. :pparam string event_id: the id of the event. :auth: required """ use_snuba = options.get('snuba.events-queries.enabled') event_cls = SnubaEvent if use_snuba else Event event = event_cls.objects.from_event_id(event_id, project.id) if event is None: return Response({'detail': 'Event not found'}, status=404) # populate event data Event.objects.bind_nodes([event], 'data') owners, rules = ProjectOwnership.get_owners(project.id, event.data) # For sake of the API, we don't differentiate between # the implicit "everyone" and no owners if owners == ProjectOwnership.Everyone: owners = [] return Response({ 'owners': serialize( Actor.resolve_many(owners), request.user, ActorSerializer(), ), # TODO(mattrobenolt): We need to change the API here to return # all rules, just keeping this way currently for API compat 'rule': rules[0].matcher if rules else None, 'rules': rules or [], })
def get(self, request, project, event_id): """ Retrieve suggested owners information for an event `````````````````````````````````````````````````` :pparam string project_slug: the slug of the project the event belongs to. :pparam string event_id: the id of the event. :auth: required """ try: event = Event.objects.get( id=event_id, project_id=project.id, ) except Event.DoesNotExist: return Response({'detail': 'Event not found'}, status=404) # populate event data Event.objects.bind_nodes([event], 'data') owners, matcher = ProjectOwnership.get_owners(project.id, event.data) # For sake of the API, we don't differentiate between # the implicit "everyone" and no owners if owners == ProjectOwnership.Everyone: owners = [] return Response({ 'owners': serialize( Actor.resolve_many(owners), request.user, ActorSerializer(), ), 'rule': matcher, })
def post(self, request, group): serializer = NoteSerializer(data=request.DATA, context={'group': group}) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) data = dict(serializer.object) mentions = data.pop('mentions', []) if Activity.objects.filter(group=group, type=Activity.NOTE, user=request.user, data=data, datetime__gte=timezone.now() - timedelta(hours=1)).exists(): return Response( '{"detail": "You have already posted that comment."}', status=status.HTTP_400_BAD_REQUEST) GroupSubscription.objects.subscribe( group=group, user=request.user, reason=GroupSubscriptionReason.comment, ) actors = Actor.resolve_many(mentions) actor_mentions = seperate_resolved_actors(actors) for user in actor_mentions.get('users'): GroupSubscription.objects.subscribe( group=group, user=user, reason=GroupSubscriptionReason.mentioned, ) mentioned_teams = actor_mentions.get('teams') mentioned_team_users = list( User.objects.filter( sentry_orgmember_set__organization_id=group.project. organization_id, sentry_orgmember_set__organizationmemberteam__team__in= mentioned_teams, sentry_orgmember_set__organizationmemberteam__is_active=True, is_active=True, ).exclude( id__in={u.id for u in actor_mentions.get('users')}).values_list( 'id', flat=True)) GroupSubscription.objects.bulk_subscribe( group=group, user_ids=mentioned_team_users, reason=GroupSubscriptionReason.team_mentioned, ) activity = Activity.objects.create( group=group, project=group.project, type=Activity.NOTE, user=extract_lazy_object(request.user), data=data, ) activity.send_notification() # sync Sentry comments to external issues if features.has('organizations:internal-catchall', group.organization, actor=request.user): external_issue_ids = GroupLink.objects.filter( project_id=group.project_id, group_id=group.id, linked_type=GroupLink.LinkedType.issue, ).values_list('linked_id', flat=True) for external_issue_id in external_issue_ids: post_comment.apply_async(kwargs={ 'external_issue_id': external_issue_id, 'data': data, }) return Response(serialize(activity, request.user), status=201)
def post(self, request, group): serializer = NoteSerializer(data=request.DATA, context={'group': group}) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) data = dict(serializer.object) mentions = data.pop('mentions', []) if Activity.objects.filter( group=group, type=Activity.NOTE, user=request.user, data=data, datetime__gte=timezone.now() - timedelta(hours=1) ).exists(): return Response( '{"detail": "You have already posted that comment."}', status=status.HTTP_400_BAD_REQUEST ) GroupSubscription.objects.subscribe( group=group, user=request.user, reason=GroupSubscriptionReason.comment, ) actors = Actor.resolve_many(mentions) actor_mentions = seperate_resolved_actors(actors) for user in actor_mentions.get('users'): GroupSubscription.objects.subscribe( group=group, user=user, reason=GroupSubscriptionReason.mentioned, ) mentioned_teams = actor_mentions.get('teams') mentioned_team_users = list( User.objects.filter( sentry_orgmember_set__organization_id=group.project.organization_id, sentry_orgmember_set__organizationmemberteam__team__in=mentioned_teams, sentry_orgmember_set__organizationmemberteam__is_active=True, is_active=True, ).exclude(id__in={u.id for u in actor_mentions.get('users')}) .values_list('id', flat=True) ) GroupSubscription.objects.bulk_subscribe( group=group, user_ids=mentioned_team_users, reason=GroupSubscriptionReason.team_mentioned, ) activity = Activity.objects.create( group=group, project=group.project, type=Activity.NOTE, user=extract_lazy_object(request.user), data=data, ) activity.send_notification() return Response(serialize(activity, request.user), status=201)
def post(self, request, work_batch_id): serializer = NoteSerializer(data=request.data, context={'work_batch': work_batch_id}) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) data = dict(serializer.validated_data) mentions = data.pop('mentions', []) if Activity.objects.filter( work_batch_id=work_batch_id, type=Activity.NOTE, user=request.user, data=data, # TODO: Hash instead? datetime__gte=timezone.now() - timedelta(hours=1)).exists(): return Response( '{"detail": "You have already posted that comment."}', status=status.HTTP_400_BAD_REQUEST) actors = Actor.resolve_many(mentions) actor_mentions = seperate_resolved_actors(actors) for user in actor_mentions.get('users'): GroupSubscription.objects.subscribe( group=1, user=user, reason=GroupSubscriptionReason.mentioned, ) # mentioned_teams = actor_mentions.get('teams') # mentioned_team_users = list( # User.objects.filter( # sentry_orgmember_set__organization_id=1, # sentry_orgmember_set__organizationmemberteam__team__in=mentioned_teams, # sentry_orgmember_set__organizationmemberteam__is_active=True, # is_active=True, # ).exclude(id__in={u.id for u in actor_mentions.get('users')}) # .values_list('id', flat=True) # ) # TODO! # GroupSubscription.objects.bulk_subscribe( # group=1, # user_ids=mentioned_team_users, # reason=GroupSubscriptionReason.team_mentioned, # ) # TODO: Org id! activity = Activity.objects.create( work_batch_id=work_batch_id, type=Activity.NOTE, user=extract_lazy_object(request.user), data=data, project_id=1, # TODO: should not be required ) activity.send_notification() return Response(serialize(activity, request.user), status=201)
def post(self, request, group): serializer = NoteSerializer(data=request.DATA, context={'group': group}) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) data = dict(serializer.object) mentions = data.pop('mentions', []) if Activity.objects.filter(group=group, type=Activity.NOTE, user=request.user, data=data, datetime__gte=timezone.now() - timedelta(hours=1)).exists(): return Response( '{"detail": "You have already posted that comment."}', status=status.HTTP_400_BAD_REQUEST) GroupSubscription.objects.subscribe( group=group, user=request.user, reason=GroupSubscriptionReason.comment, ) actors = Actor.resolve_many(mentions) actor_mentions = seperate_resolved_actors(actors) for user in actor_mentions.get('users'): GroupSubscription.objects.subscribe( group=group, user=user, reason=GroupSubscriptionReason.mentioned, ) mentioned_teams = actor_mentions.get('teams') mentioned_team_users = User.objects.filter( sentry_orgmember_set__organization_id=group.project. organization_id, sentry_orgmember_set__organizationmemberteam__team__in= mentioned_teams, sentry_orgmember_set__organizationmemberteam__is_active=True, is_active=True, ).exclude(id__in={u.id for u in actor_mentions.get('users')}) for user in mentioned_team_users: GroupSubscription.objects.subscribe( group=group, user=user, reason=GroupSubscriptionReason.team_mentioned, ) activity = Activity.objects.create( group=group, project=group.project, type=Activity.NOTE, user=extract_lazy_object(request.user), data=data, ) activity.send_notification() return Response(serialize(activity, request.user), status=201)