Example #1
0
    def handle_assign_to(
        self,
        integration: Integration,
        external_issue_key: str,
        assigned_to: Optional[Mapping[str, str]],
    ) -> None:
        if not assigned_to:
            return

        email: Optional[str] = None
        assign = False

        new_value = assigned_to.get("newValue")
        if new_value is not None:
            try:
                email = self.parse_email(new_value)
            except AttributeError as e:
                logger.info(
                    "vsts.failed-to-parse-email-in-handle-assign-to",
                    extra={
                        "error": str(e),
                        "integration_id": integration.id,
                        "assigned_to_values": assigned_to,
                        "external_issue_key": external_issue_key,
                    },
                )
                return  # TODO(lb): return if cannot parse email?
            assign = True

        sync_group_assignee_inbound(
            integration=integration,
            email=email,
            external_issue_key=external_issue_key,
            assign=assign,
        )
Example #2
0
def handle_assignee_change(
    integration: Integration,
    data: Mapping[str, Any],
    use_email_scope: bool = False,
) -> None:
    assignee_changed = any(item for item in data["changelog"]["items"]
                           if item["field"] == "assignee")
    if not assignee_changed:
        return

    fields = data["issue"]["fields"]

    # If there is no assignee, assume it was unassigned.
    assignee = fields.get("assignee")
    issue_key = data["issue"]["key"]

    if assignee is None:
        sync_group_assignee_inbound(integration, None, issue_key, assign=False)
        return

    email = get_assignee_email(integration, assignee, use_email_scope)
    # TODO(steve) check display name
    if not email:
        logger.info(
            "missing-assignee-email",
            extra={
                "issue_key": issue_key,
                "integration_id": integration.id
            },
        )
        return

    sync_group_assignee_inbound(integration, email, issue_key, assign=True)
Example #3
0
def handle_assign_to(
    integration: Integration,
    external_issue_key: str | None,
    assigned_to: Mapping[str, str] | None,
) -> None:
    if not assigned_to:
        return

    email: str | None = None
    assign = False

    new_value = assigned_to.get("newValue")
    if new_value is not None:
        email = parse_email(new_value)
        if not email:
            logger.info(
                "vsts.failed-to-parse-email-in-handle-assign-to",
                extra={
                    "error": "parse_error",
                    "integration_id": integration.id,
                    "assigned_to_values": assigned_to,
                    "external_issue_key": external_issue_key,
                },
            )
            return  # TODO(mgaeta): return if cannot parse email?
        assign = True

    sync_group_assignee_inbound(
        integration=integration,
        email=email,
        external_issue_key=external_issue_key,
        assign=assign,
    )
Example #4
0
    def test_assignee_sync_inbound_assign(self):
        group = self.group
        user_no_access = self.create_user()
        user_w_access = self.user
        integration = Integration.objects.create(provider="example", external_id="123456")
        integration.add_organization(group.organization, user_no_access)

        OrganizationIntegration.objects.filter(
            integration_id=integration.id, organization_id=group.organization.id
        ).update(
            config={
                "sync_comments": True,
                "sync_status_outbound": True,
                "sync_status_inbound": True,
                "sync_assignee_outbound": True,
                "sync_assignee_inbound": True,
            }
        )

        external_issue = ExternalIssue.objects.create(
            organization_id=group.organization.id, integration_id=integration.id, key="APP-123"
        )

        GroupLink.objects.create(
            group_id=group.id,
            project_id=group.project_id,
            linked_type=GroupLink.LinkedType.issue,
            linked_id=external_issue.id,
            relationship=GroupLink.Relationship.references,
        )

        with self.feature("organizations:integrations-issue-sync"):
            # no permissions
            groups_updated = sync_group_assignee_inbound(
                integration, user_no_access.email, "APP-123"
            )

            assert not groups_updated

            # w permissions
            groups_updated = sync_group_assignee_inbound(
                integration, user_w_access.email, "APP-123"
            )

            assert groups_updated[0] == group
            assert GroupAssignee.objects.filter(
                project=group.project, group=group, user=user_w_access, team__isnull=True
            ).exists()

            # confirm capitalization doesn't affect syncing
            groups_updated = sync_group_assignee_inbound(
                integration, user_w_access.email.title(), "APP-123"
            )

            assert groups_updated[0] == group
            assert GroupAssignee.objects.filter(
                project=group.project, group=group, user=user_w_access, team__isnull=True
            ).exists()
Example #5
0
def handle_assignee_change(integration, data, use_email_scope=False):
    assignee_changed = any(item for item in data["changelog"]["items"]
                           if item["field"] == "assignee")
    if not assignee_changed:
        return

    fields = data["issue"]["fields"]

    # if no assignee, assume it was unassigned
    assignee = fields.get("assignee")
    issue_key = data["issue"]["key"]

    if assignee is None:
        sync_group_assignee_inbound(integration, None, issue_key, assign=False)
        return
    email = assignee.get("emailAddress")
    # pull email from API if we can use it
    if not email and use_email_scope:
        account_id = assignee.get("accountId")
        client = JiraApiClient(
            integration.metadata["base_url"],
            JiraCloud(integration.metadata["shared_secret"]),
            verify_ssl=True,
        )
        email = client.get_email(account_id)

    # TODO(steve) check display name
    if not email:
        logger.info(
            "missing-assignee-email",
            extra={
                "issue_key": issue_key,
                "integration_id": integration.id
            },
        )
        return

    sync_group_assignee_inbound(integration, email, issue_key, assign=True)
Example #6
0
    def test_assignee_sync_inbound_deassign(self):
        group = self.group
        integration = Integration.objects.create(provider="example",
                                                 external_id="123456")
        integration.add_organization(group.organization, self.user)

        OrganizationIntegration.objects.filter(
            integration_id=integration.id,
            organization_id=group.organization.id).update(
                config={
                    "sync_comments": True,
                    "sync_status_outbound": True,
                    "sync_status_inbound": True,
                    "sync_assignee_outbound": True,
                    "sync_assignee_inbound": True,
                })

        external_issue = ExternalIssue.objects.create(
            organization_id=group.organization.id,
            integration_id=integration.id,
            key="APP-123")

        GroupLink.objects.create(
            group_id=group.id,
            project_id=group.project_id,
            linked_type=GroupLink.LinkedType.issue,
            linked_id=external_issue.id,
            relationship=GroupLink.Relationship.references,
        )

        GroupAssignee.objects.assign(group, self.user)

        with self.feature("organizations:integrations-issue-sync"):
            groups_updated = sync_group_assignee_inbound(integration,
                                                         self.user.email,
                                                         "APP-123",
                                                         assign=False)

            assert groups_updated[0] == group
            assert not GroupAssignee.objects.filter(
                project=group.project,
                group=group,
                user=self.user,
                team__isnull=True).exists()