예제 #1
0
    def get(self, request, organization):
        """
        List an Organization's Teams
        ````````````````````````````

        Return a list of teams bound to a organization.

        :pparam string organization_slug: the slug of the organization for
                                          which the teams should be listed.
        :auth: required
        """
        # TODO(dcramer): this should be system-wide default for organization
        # based endpoints
        if request.auth and hasattr(request.auth, 'project'):
            return Response(status=403)

        team_list = list(
            Team.objects.filter(
                organization=organization,
                status=TeamStatus.VISIBLE,
            ).order_by('name', 'slug'))

        return Response(
            serialize(team_list, request.user, TeamWithProjectsSerializer()))
예제 #2
0
    def test_simple(self):
        user = self.create_user(username='******')
        organization = self.create_organization(owner=user)
        team = self.create_team(organization=organization)
        project = self.create_project(teams=[team],
                                      organization=organization,
                                      name='foo')
        project2 = self.create_project(teams=[team],
                                       organization=organization,
                                       name='bar')

        result = serialize(team, user, TeamWithProjectsSerializer())
        result.pop('dateCreated')

        # don't compare dateCreated because of mysql
        serialized_projects = serialize([project2, project], user)
        for p in serialized_projects:
            p.pop('dateCreated')

        for p in result['projects']:
            p.pop('dateCreated')

        assert result == {
            'slug': team.slug,
            'name': team.name,
            'hasAccess': True,
            'isPending': False,
            'isMember': False,
            'id': six.text_type(team.id),
            'projects': serialized_projects,
            'avatar': {
                'avatarType': 'letter_avatar',
                'avatarUuid': None,
            },
            'memberCount': 0
        }
    def post(self, request, organization, member_id, team_slug):
        """
        Join a team

        Join or request access to a team.

        If the user is already a member of the team, this will simply return
        a 204.

        If the user needs permission to join the team, an access request will
        be generated and the returned status code will be 202.
        """
        try:
            om = self._get_member(request, organization, member_id)
        except OrganizationMember.DoesNotExist:
            raise ResourceDoesNotExist

        if not self._can_access(request, om):
            return Response({'detail': ERR_INSUFFICIENT_ROLE}, status=400)

        try:
            team = Team.objects.get(
                organization=organization,
                slug=team_slug,
            )
        except Team.DoesNotExist:
            raise ResourceDoesNotExist

        try:
            omt = OrganizationMemberTeam.objects.get(
                team=team,
                organizationmember=om,
            )
        except OrganizationMemberTeam.DoesNotExist:
            if not (request.access.has_scope('org:write')
                    or organization.flags.allow_joinleave):
                omt, created = OrganizationAccessRequest.objects.get_or_create(
                    team=team,
                    member=om,
                )
                if created:
                    omt.send_request_email()
                return Response(status=202)

            omt = OrganizationMemberTeam.objects.create(
                team=team,
                organizationmember=om,
            )
        else:
            return Response(status=204)

        self.create_audit_entry(
            request=request,
            organization=organization,
            target_object=omt.id,
            target_user=om.user,
            event=AuditLogEntryEvent.MEMBER_JOIN_TEAM,
            data=omt.get_audit_log_data(),
        )

        return Response(serialize(team, request.user,
                                  TeamWithProjectsSerializer()),
                        status=201)
예제 #4
0
    def serialize(self, obj, attrs, user):
        from sentry import features
        from sentry.app import env
        from sentry.api.serializers.models.team import TeamWithProjectsSerializer

        team_list = list(
            Team.objects.filter(
                organization=obj,
                status=TeamStatus.VISIBLE,
            ))
        for team in team_list:
            team._organization_cache = obj

        onboarding_tasks = list(
            OrganizationOnboardingTask.objects.filter(
                organization=obj, ).select_related('user'))

        feature_list = []
        if features.has('organizations:sso', obj, actor=user):
            feature_list.append('sso')
        if features.has('organizations:onboarding', obj, actor=user) and \
                not OrganizationOption.objects.filter(organization=obj).exists():
            feature_list.append('onboarding')
        if features.has('organizations:api-keys', obj, actor=user) or \
                ApiKey.objects.filter(organization=obj).exists():
            feature_list.append('api-keys')
        if features.has('organizations:group-unmerge', obj, actor=user):
            feature_list.append('group-unmerge')
        if features.has('organizations:integrations-v3', obj, actor=user):
            feature_list.append('integrations-v3')
        if features.has('organizations:new-settings', obj, actor=user):
            feature_list.append('new-settings')
        if features.has('organizations:require-2fa', obj, actor=user):
            feature_list.append('require-2fa')
        if features.has('organizations:environments', obj, actor=user):
            feature_list.append('environments')
        if features.has('organizations:repos', obj, actor=user):
            feature_list.append('repos')
        if features.has('organizations:internal-catchall', obj, actor=user):
            feature_list.append('internal-catchall')

        if getattr(obj.flags, 'allow_joinleave'):
            feature_list.append('open-membership')
        if not getattr(obj.flags, 'disable_shared_issues'):
            feature_list.append('shared-issues')
        if getattr(obj.flags, 'require_2fa'):
            feature_list.append('require-2fa')

        context = super(DetailedOrganizationSerializer,
                        self).serialize(obj, attrs, user)
        max_rate = quotas.get_maximum_quota(obj)
        context['quota'] = {
            'maxRate':
            max_rate[0],
            'maxRateInterval':
            max_rate[1],
            'accountLimit':
            int(
                OrganizationOption.objects.get_value(
                    organization=obj,
                    key='sentry:account-rate-limit',
                    default=0,
                )),
            'projectLimit':
            int(
                OrganizationOption.objects.get_value(
                    organization=obj,
                    key='sentry:project-rate-limit',
                    default=100,
                )),
        }

        context.update({
            'isDefault':
            obj.is_default,
            'defaultRole':
            obj.default_role,
            'availableRoles': [{
                'id': r.id,
                'name': r.name,
            } for r in roles.get_all()],
            'openMembership':
            bool(obj.flags.allow_joinleave),
            'require2FA':
            bool(obj.flags.require_2fa),
            'allowSharedIssues':
            not obj.flags.disable_shared_issues,
            'enhancedPrivacy':
            bool(obj.flags.enhanced_privacy),
            'dataScrubber':
            bool(obj.get_option('sentry:require_scrub_data', False)),
            'dataScrubberDefaults':
            bool(obj.get_option('sentry:require_scrub_defaults', False)),
            'sensitiveFields':
            obj.get_option('sentry:sensitive_fields', None) or [],
            'safeFields':
            obj.get_option('sentry:safe_fields', None) or [],
            'scrubIPAddresses':
            bool(obj.get_option('sentry:require_scrub_ip_address', False)),
        })
        context['teams'] = serialize(team_list, user,
                                     TeamWithProjectsSerializer())
        if env.request:
            context['access'] = access.from_request(env.request, obj).scopes
        else:
            context['access'] = access.from_user(user, obj).scopes
        context['features'] = feature_list
        context[
            'pendingAccessRequests'] = OrganizationAccessRequest.objects.filter(
                team__organization=obj, ).count()
        context['onboardingTasks'] = serialize(onboarding_tasks, user,
                                               OnboardingTasksSerializer())
        return context
예제 #5
0
    def serialize(self, obj, attrs, user):
        from sentry import features
        from sentry.app import env
        from sentry.api.serializers.models.team import TeamWithProjectsSerializer

        team_list = list(
            Team.objects.filter(
                organization=obj,
                status=TeamStatus.VISIBLE,
            ))
        for team in team_list:
            team._organization_cache = obj

        onboarding_tasks = list(
            OrganizationOnboardingTask.objects.filter(
                organization=obj, ).select_related('user'))

        feature_list = []
        if features.has('organizations:repos', obj, actor=user):
            feature_list.append('repos')
        if features.has('organizations:sso', obj, actor=user):
            feature_list.append('sso')
        if features.has('organizations:callsigns', obj, actor=user):
            feature_list.append('callsigns')
        if features.has('organizations:onboarding', obj, actor=user) and \
                not OrganizationOption.objects.filter(organization=obj).exists():
            feature_list.append('onboarding')
        if features.has('organizations:api-keys', obj, actor=user) or \
                ApiKey.objects.filter(organization=obj).exists():
            feature_list.append('api-keys')

        if getattr(obj.flags, 'allow_joinleave'):
            feature_list.append('open-membership')
        if not getattr(obj.flags, 'disable_shared_issues'):
            feature_list.append('shared-issues')

        context = super(DetailedOrganizationSerializer,
                        self).serialize(obj, attrs, user)
        context['quota'] = {
            'maxRate':
            quotas.get_organization_quota(obj),
            'projectLimit':
            int(
                OrganizationOption.objects.get_value(
                    organization=obj,
                    key='sentry:project-rate-limit',
                    default=100,
                )),
        }
        context['teams'] = serialize(team_list, user,
                                     TeamWithProjectsSerializer())
        if env.request:
            context['access'] = access.from_request(env.request, obj).scopes
        else:
            context['access'] = access.from_user(user, obj).scopes
        context['features'] = feature_list
        context[
            'pendingAccessRequests'] = OrganizationAccessRequest.objects.filter(
                team__organization=obj, ).count()
        context['onboardingTasks'] = serialize(onboarding_tasks, user,
                                               OnboardingTasksSerializer())
        return context
예제 #6
0
    def post(self, request, organization, member_id, team_slug):
        """
        Join a team

        Join or request access to a team.

        If the user is already a member of the team, this will simply return
        a 204.

        If the user needs permission to join the team, an access request will
        be generated and the returned status code will be 202.
        """
        try:
            om = self._get_member(request, organization, member_id)
        except OrganizationMember.DoesNotExist:
            raise ResourceDoesNotExist

        if not self._can_access(request, om):
            return Response({'detail': ERR_INSUFFICIENT_ROLE}, status=400)

        try:
            team = Team.objects.get(
                organization=organization,
                slug=team_slug,
            )
        except Team.DoesNotExist:
            raise ResourceDoesNotExist

        if not om.has_global_access:
            try:
                omt = OrganizationMemberTeam.objects.get(
                    team=team,
                    organizationmember=om,
                )
            except OrganizationMemberTeam.DoesNotExist:
                # TODO(dcramer): this should create a pending request and
                # return a 202
                if not organization.flags.allow_joinleave:
                    omt, created = OrganizationAccessRequest.objects.get_or_create(
                        team=team,
                        member=om,
                    )
                    if created:
                        omt.send_request_email()
                    return Response(status=202)

                omt = OrganizationMemberTeam(
                    team=team,
                    organizationmember=om,
                    is_active=False,
                )

            if omt.is_active:
                return Response(status=204)
        else:
            try:
                omt = OrganizationMemberTeam.objects.get(
                    team=team,
                    organizationmember=om,
                )
            except OrganizationMemberTeam.DoesNotExist:
                # if the relationship doesnt exist, they're already a member
                return Response(status=204)

        omt.is_active = True
        omt.save()

        self.create_audit_entry(
            request=request,
            organization=organization,
            target_object=omt.id,
            target_user=om.user,
            event=AuditLogEntryEvent.MEMBER_JOIN_TEAM,
            data=omt.get_audit_log_data(),
        )

        return Response(serialize(team, request.user,
                                  TeamWithProjectsSerializer()),
                        status=201)
예제 #7
0
    def delete(self, request, organization, member_id, team_slug):
        """
        Leave a team

        Leave a team.
        """
        try:
            om = self._get_member(request, organization, member_id)
        except OrganizationMember.DoesNotExist:
            raise ResourceDoesNotExist

        if not self._can_access(request, om):
            return Response({'detail': ERR_INSUFFICIENT_ROLE}, status=400)

        try:
            team = Team.objects.get(
                organization=organization,
                slug=team_slug,
            )
        except Team.DoesNotExist:
            raise ResourceDoesNotExist

        if not om.has_global_access:
            try:
                omt = OrganizationMemberTeam.objects.get(
                    team=team,
                    organizationmember=om,
                )
            except OrganizationMemberTeam.DoesNotExist:
                # if the relationship doesnt exist, they're already a member
                return Response(serialize(team, request.user,
                                          TeamWithProjectsSerializer()),
                                status=200)
        else:
            try:
                omt = OrganizationMemberTeam.objects.get(
                    team=team,
                    organizationmember=om,
                    is_active=True,
                )
            except OrganizationMemberTeam.DoesNotExist:
                omt = OrganizationMemberTeam(
                    team=team,
                    organizationmember=om,
                    is_active=True,
                )

        if omt.is_active:
            omt.is_active = False
            omt.save()

            self.create_audit_entry(
                request=request,
                organization=organization,
                target_object=omt.id,
                target_user=om.user,
                event=AuditLogEntryEvent.MEMBER_LEAVE_TEAM,
                data=omt.get_audit_log_data(),
            )

        return Response(serialize(team, request.user,
                                  TeamWithProjectsSerializer()),
                        status=200)