예제 #1
0
    def _get_actions(self, request: Request, group):
        project = group.project

        action_list = []
        for plugin in plugins.for_project(project, version=1):
            if is_plugin_deprecated(plugin, project):
                continue

            results = safe_execute(plugin.actions,
                                   request,
                                   group,
                                   action_list,
                                   _with_transaction=False)

            if not results:
                continue

            action_list = results

        for plugin in plugins.for_project(project, version=2):
            if is_plugin_deprecated(plugin, project):
                continue
            for action in (safe_execute(
                    plugin.get_actions, request, group,
                    _with_transaction=False) or ()):
                action_list.append(action)

        return action_list
예제 #2
0
    def _get_available_issue_plugins(self, request, group):
        project = group.project

        plugin_issues = []
        for plugin in plugins.for_project(project, version=1):
            if isinstance(plugin, IssueTrackingPlugin2):
                if is_plugin_deprecated(plugin, project):
                    continue
                plugin_issues = safe_execute(
                    plugin.plugin_issues, request, group, plugin_issues, _with_transaction=False
                )
        return plugin_issues
예제 #3
0
def get_annotations(group, request=None):
    project = group.project

    annotation_list = []
    for plugin in plugins.for_project(project, version=2):
        if is_plugin_deprecated(plugin, project):
            continue
        for value in (safe_execute(
                plugin.get_annotations, group=group, _with_transaction=False)
                      or ()):
            annotation = safe_execute(Annotation,
                                      _with_transaction=False,
                                      **value)
            if annotation:
                annotation_list.append(annotation)

    return annotation_list
예제 #4
0
    def handle(self, request: Request, organization, project, group_id,
               slug) -> Response:
        group = get_object_or_404(Group, pk=group_id, project=project)

        try:
            plugin = plugins.get(slug)
            if is_plugin_deprecated(plugin, project):
                raise Http404("Plugin not found")
        except KeyError:
            raise Http404("Plugin not found")

        GroupMeta.objects.populate_cache([group])

        response = plugin.get_view_response(request, group)
        if response:
            return response

        redirect = request.META.get("HTTP_REFERER", "")
        if not is_safe_url(redirect, allowed_hosts=(request.get_host(), )):
            redirect = f"/{organization.slug}/{group.project.slug}/"
        return HttpResponseRedirect(redirect)
예제 #5
0
    def get_attrs(self, item_list, user):
        from sentry.integrations import IntegrationFeatures
        from sentry.models import PlatformExternalIssue
        from sentry.plugins.base import plugins

        GroupMeta.objects.populate_cache(item_list)

        # Note that organization is necessary here for use in `_get_permalink` to avoid
        # making unnecessary queries.
        prefetch_related_objects(item_list, "project__organization")

        if user.is_authenticated and item_list:
            bookmarks = set(
                GroupBookmark.objects.filter(
                    user=user, group__in=item_list).values_list("group_id",
                                                                flat=True))
            seen_groups = dict(
                GroupSeen.objects.filter(user=user,
                                         group__in=item_list).values_list(
                                             "group_id", "last_seen"))
            subscriptions = self._get_subscriptions(item_list, user)
        else:
            bookmarks = set()
            seen_groups = {}
            subscriptions = defaultdict(lambda: (False, False, None))

        assignees = {
            a.group_id: a.assigned_actor()
            for a in GroupAssignee.objects.filter(group__in=item_list)
        }
        resolved_assignees = ActorTuple.resolve_dict(assignees)

        ignore_items = {
            g.group_id: g
            for g in GroupSnooze.objects.filter(group__in=item_list)
        }

        resolved_item_list = [
            i for i in item_list if i.status == GroupStatus.RESOLVED
        ]
        if resolved_item_list:
            release_resolutions = {
                i[0]: i[1:]
                for i in GroupResolution.objects.filter(
                    group__in=resolved_item_list).values_list(
                        "group", "type", "release__version", "actor_id")
            }

            # due to our laziness, and django's inability to do a reasonable join here
            # we end up with two queries
            commit_results = list(
                Commit.objects.extra(
                    select={"group_id": "sentry_grouplink.group_id"},
                    tables=["sentry_grouplink"],
                    where=[
                        "sentry_grouplink.linked_id = sentry_commit.id",
                        "sentry_grouplink.group_id IN ({})".format(", ".join(
                            str(i.id) for i in resolved_item_list)),
                        "sentry_grouplink.linked_type = %s",
                        "sentry_grouplink.relationship = %s",
                    ],
                    params=[
                        int(GroupLink.LinkedType.commit),
                        int(GroupLink.Relationship.resolves)
                    ],
                ))
            commit_resolutions = {
                i.group_id: d
                for i, d in zip(commit_results, serialize(
                    commit_results, user))
            }
        else:
            release_resolutions = {}
            commit_resolutions = {}

        actor_ids = {r[-1] for r in release_resolutions.values()}
        actor_ids.update(r.actor_id for r in ignore_items.values())
        if actor_ids:
            users = list(User.objects.filter(id__in=actor_ids, is_active=True))
            actors = {u.id: d for u, d in zip(users, serialize(users, user))}
        else:
            actors = {}

        share_ids = dict(
            GroupShare.objects.filter(group__in=item_list).values_list(
                "group_id", "uuid"))

        result = {}

        seen_stats = self._get_seen_stats(item_list, user)

        annotations_by_group_id = defaultdict(list)

        organization_id_list = list(
            {item.project.organization_id
             for item in item_list})
        # if no groups, then we can't proceed but this seems to be a valid use case
        if not item_list:
            return {}
        if len(organization_id_list) > 1:
            # this should never happen but if it does we should know about it
            logger.warning(
                "Found multiple organizations for groups: %s, with orgs: %s" %
                ([item.id for item in item_list], organization_id_list))

        # should only have 1 org at this point
        organization_id = organization_id_list[0]

        authorized = self._is_authorized(user, organization_id)

        # find all the integration installs that have issue tracking
        for integration in Integration.objects.filter(
                organizations=organization_id):
            if not (integration.has_feature(IntegrationFeatures.ISSUE_BASIC) or
                    integration.has_feature(IntegrationFeatures.ISSUE_SYNC)):
                continue

            install = integration.get_installation(organization_id)
            local_annotations_by_group_id = (safe_execute(
                install.get_annotations_for_group_list,
                group_list=item_list,
                _with_transaction=False,
            ) or {})
            merge_list_dictionaries(annotations_by_group_id,
                                    local_annotations_by_group_id)

        # find the external issues for sentry apps and add them in
        local_annotations_by_group_id = (safe_execute(
            PlatformExternalIssue.get_annotations_for_group_list,
            group_list=item_list,
            _with_transaction=False,
        ) or {})
        merge_list_dictionaries(annotations_by_group_id,
                                local_annotations_by_group_id)

        snuba_stats = self._get_group_snuba_stats(item_list, seen_stats)

        for item in item_list:
            active_date = item.active_at or item.first_seen

            annotations = []
            annotations.extend(annotations_by_group_id[item.id])

            # add the annotations for plugins
            # note that the model GroupMeta where all the information is stored is already cached at the top of this function
            # so these for loops doesn't make a bunch of queries
            for plugin in plugins.for_project(project=item.project, version=1):
                if is_plugin_deprecated(plugin, item.project):
                    continue
                safe_execute(plugin.tags,
                             None,
                             item,
                             annotations,
                             _with_transaction=False)
            for plugin in plugins.for_project(project=item.project, version=2):
                annotations.extend(
                    safe_execute(plugin.get_annotations,
                                 group=item,
                                 _with_transaction=False) or ())

            resolution_actor = None
            resolution_type = None
            resolution = release_resolutions.get(item.id)
            if resolution:
                resolution_type = "release"
                resolution_actor = actors.get(resolution[-1])
            if not resolution:
                resolution = commit_resolutions.get(item.id)
                if resolution:
                    resolution_type = "commit"

            ignore_item = ignore_items.get(item.id)
            if ignore_item:
                ignore_actor = actors.get(ignore_item.actor_id)
            else:
                ignore_actor = None

            result[item] = {
                "id": item.id,
                "assigned_to": resolved_assignees.get(item.id),
                "is_bookmarked": item.id in bookmarks,
                "subscription": subscriptions[item.id],
                "has_seen":
                seen_groups.get(item.id, active_date) > active_date,
                "annotations": annotations,
                "ignore_until": ignore_item,
                "ignore_actor": ignore_actor,
                "resolution": resolution,
                "resolution_type": resolution_type,
                "resolution_actor": resolution_actor,
                "share_id": share_ids.get(item.id),
                "authorized": authorized,
            }

            result[item]["is_unhandled"] = bool(
                snuba_stats.get(item.id, {}).get("unhandled"))

            if seen_stats:
                result[item].update(seen_stats.get(item, {}))
        return result