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. :param string detailed: Specify "0" to return team details that do not include projects :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) queryset = Team.objects.filter( organization=organization, status=TeamStatus.VISIBLE ).order_by("slug") query = request.GET.get("query") if query: tokens = tokenize_query(query) for key, value in tokens.items(): if key == "hasExternalTeams": has_external_teams = "true" in value if has_external_teams: queryset = queryset.filter( actor_id__in=ExternalActor.objects.filter( organization=organization ).values_list("actor_id") ) else: queryset = queryset.exclude( actor_id__in=ExternalActor.objects.filter( organization=organization ).values_list("actor_id") ) elif key == "query": value = " ".join(value) queryset = queryset.filter(Q(name__icontains=value) | Q(slug__icontains=value)) elif key == "slug": queryset = queryset.filter(slug__in=value) else: queryset = queryset.none() is_detailed = request.GET.get("detailed", "1") != "0" expand = ["projects", "externalTeams"] if is_detailed else [] return self.paginate( request=request, queryset=queryset, order_by="slug", on_results=lambda x: serialize(x, request.user, TeamSerializer(expand=expand)), paginator_cls=OffsetPaginator, )
def serialize(self, obj, attrs, user, access): from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer context = super().serialize(obj, attrs, user, access) team_list = self._team_list(obj, access) project_list = self._project_list(obj, access) context["teams"] = serialize(team_list, user, TeamSerializer()) context["projects"] = serialize(project_list, user, ProjectSummarySerializer()) return context
def serialize(self, obj, attrs, user, access): from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer context = super(DetailedOrganizationSerializerWithProjectsAndTeams, self).serialize(obj, attrs, user, access) team_list = self._team_list(obj, access) project_list = self._project_list(obj, access) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) return context
def serialize( # type: ignore self, obj: Organization, attrs: Mapping[str, Any], user: User, access: Access ) -> DetailedOrganizationSerializerWithProjectsAndTeamsResponse: from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer context = cast( DetailedOrganizationSerializerWithProjectsAndTeamsResponse, super().serialize(obj, attrs, user, access), ) team_list = self._team_list(obj, access) project_list = self._project_list(obj, access) context["teams"] = serialize(team_list, user, TeamSerializer()) context["projects"] = serialize(project_list, user, ProjectSummarySerializer()) return context
def serialize(self, obj, attrs, user, access): from sentry import experiments from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = self._team_list(obj, access) project_list = self._project_list(obj, access) onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj, ).select_related('user')) experiment_assignments = experiments.all(org=obj, actor=user) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context['experiments'] = experiment_assignments context['quota'] = { 'maxRate': max_rate[0], 'maxRateInterval': max_rate[1], 'accountLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:account-rate-limit', default=ACCOUNT_RATE_LIMIT_DEFAULT, )), 'projectLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:project-rate-limit', default=PROJECT_RATE_LIMIT_DEFAULT, )), } 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', REQUIRE_SCRUB_DATA_DEFAULT)), 'dataScrubberDefaults': bool( obj.get_option('sentry:require_scrub_defaults', REQUIRE_SCRUB_DEFAULTS_DEFAULT)), 'sensitiveFields': obj.get_option('sentry:sensitive_fields', SENSITIVE_FIELDS_DEFAULT) or [], 'safeFields': obj.get_option('sentry:safe_fields', SAFE_FIELDS_DEFAULT) or [], 'storeCrashReports': bool( obj.get_option('sentry:store_crash_reports', STORE_CRASH_REPORTS_DEFAULT)), 'scrubIPAddresses': bool( obj.get_option('sentry:require_scrub_ip_address', REQUIRE_SCRUB_IP_ADDRESS_DEFAULT)), 'scrapeJavaScript': bool( obj.get_option('sentry:scrape_javascript', SCRAPE_JAVASCRIPT_DEFAULT)), 'trustedRelays': obj.get_option('sentry:trusted-relays', TRUSTED_RELAYS_DEFAULT) or [], }) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) context['access'] = access.scopes context[ 'pendingAccessRequests'] = OrganizationAccessRequest.objects.filter( team__organization=obj, ).count() context['onboardingTasks'] = serialize(onboarding_tasks, user, OnboardingTasksSerializer()) return context
def serialize(self, obj, attrs, user): from sentry import features from sentry.app import env from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = list(Team.objects.filter( organization=obj, status=TeamStatus.VISIBLE, )) for team in team_list: team._organization_cache = obj project_list = list(Project.objects.filter( organization=obj, status=ProjectStatus.VISIBLE, )) for project in project_list: project._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:github-apps', obj, actor=user): feature_list.append('github-apps') 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 features.has('organizations:suggested-commits', obj, actor=user): feature_list.append('suggested-commits') if features.has('organizations:new-teams', obj, actor=user): feature_list.append('new-teams') if features.has('organizations:unreleased-changes', obj, actor=user): feature_list.append('unreleased-changes') if features.has('organizations:relay', obj, actor=user): feature_list.append('relay') if features.has('organizations:health', obj, actor=user): feature_list.append('health') 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, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) 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
def team_serializer_for_post(self): # allow child routes to supply own serializer, used in SCIM teams route return TeamSerializer()
def serialize(self, obj, attrs, user): from sentry import features, experiments from sentry.features.base import OrganizationFeature from sentry.app import env from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = sorted(Team.objects.filter( organization=obj, status=TeamStatus.VISIBLE, ), key=lambda x: x.slug) for team in team_list: team._organization_cache = obj project_list = sorted(Project.objects.filter( organization=obj, status=ProjectStatus.VISIBLE, ), key=lambda x: x.slug) for project in project_list: project._organization_cache = obj onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj, ).select_related('user') ) # Retrieve all registered organization features org_features = features.all(feature_type=OrganizationFeature).keys() feature_list = set() for feature_name in org_features: if not feature_name.startswith('organizations:'): continue if features.has(feature_name, obj, actor=user): # Remove the organization scope prefix feature_list.add(feature_name[len('organizations:'):]) # Do not include the onboarding feature if OrganizationOptions exist if 'onboarding' in feature_list and \ OrganizationOption.objects.filter(organization=obj).exists(): feature_list.remove('onboarding') # Include api-keys feature if they previously had any api-keys if 'api-keys' not in feature_list and ApiKey.objects.filter(organization=obj).exists(): feature_list.add('api-keys') # Organization flag features (not provided through the features module) if OrganizationOption.objects.filter( organization=obj, key__in=LEGACY_RATE_LIMIT_OPTIONS).exists(): feature_list.add('legacy-rate-limits') if getattr(obj.flags, 'allow_joinleave'): # noqa: B009 feature_list.add('open-membership') if not getattr(obj.flags, 'disable_shared_issues'): # noqa: B009 feature_list.add('shared-issues') if getattr(obj.flags, 'require_2fa'): # noqa: B009 feature_list.add('require-2fa') experiment_assignments = experiments.all(org=obj, actor=user) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context['experiments'] = experiment_assignments context['quota'] = { 'maxRate': max_rate[0], 'maxRateInterval': max_rate[1], 'accountLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:account-rate-limit', default=ACCOUNT_RATE_LIMIT_DEFAULT, ) ), 'projectLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:project-rate-limit', default=PROJECT_RATE_LIMIT_DEFAULT, ) ), } 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', REQUIRE_SCRUB_DATA_DEFAULT)), 'dataScrubberDefaults': bool(obj.get_option('sentry:require_scrub_defaults', REQUIRE_SCRUB_DEFAULTS_DEFAULT)), 'sensitiveFields': obj.get_option('sentry:sensitive_fields', SENSITIVE_FIELDS_DEFAULT) or [], 'safeFields': obj.get_option('sentry:safe_fields', SAFE_FIELDS_DEFAULT) or [], 'storeCrashReports': bool(obj.get_option('sentry:store_crash_reports', STORE_CRASH_REPORTS_DEFAULT)), 'scrubIPAddresses': bool(obj.get_option('sentry:require_scrub_ip_address', REQUIRE_SCRUB_IP_ADDRESS_DEFAULT)), 'scrapeJavaScript': bool(obj.get_option('sentry:scrape_javascript', SCRAPE_JAVASCRIPT_DEFAULT)), 'trustedRelays': obj.get_option('sentry:trusted-relays', TRUSTED_RELAYS_DEFAULT) or [], }) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) 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
def serialize(self, obj, attrs, user): from sentry import features, experiments from sentry.app import env from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = sorted(Team.objects.filter( organization=obj, status=TeamStatus.VISIBLE, ), key=lambda x: x.slug) for team in team_list: team._organization_cache = obj project_list = sorted(Project.objects.filter( organization=obj, status=ProjectStatus.VISIBLE, ), key=lambda x: x.slug) for project in project_list: project._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:github-apps', obj, actor=user): feature_list.append('github-apps') if features.has('organizations:require-2fa', obj, actor=user): feature_list.append('require-2fa') 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 features.has('organizations:new-issue-ui', obj, actor=user): feature_list.append('new-issue-ui') if features.has('organizations:github-enterprise', obj, actor=user): feature_list.append('github-enterprise') if features.has('organizations:bitbucket-integration', obj, actor=user): feature_list.append('bitbucket-integration') if features.has('organizations:jira-integration', obj, actor=user): feature_list.append('jira-integration') if features.has('organizations:vsts-integration', obj, actor=user): feature_list.append('vsts-integration') if features.has('organizations:integrations-issue-basic', obj, actor=user): feature_list.append('integrations-issue-basic') if features.has('organizations:integrations-issue-sync', obj, actor=user): feature_list.append('integrations-issue-sync') if features.has('organizations:suggested-commits', obj, actor=user): feature_list.append('suggested-commits') if features.has('organizations:new-teams', obj, actor=user): feature_list.append('new-teams') if features.has('organizations:unreleased-changes', obj, actor=user): feature_list.append('unreleased-changes') if features.has('organizations:relay', obj, actor=user): feature_list.append('relay') if features.has('organizations:js-loader', obj, actor=user): feature_list.append('js-loader') if features.has('organizations:health', obj, actor=user): feature_list.append('health') if features.has('organizations:discover', obj, actor=user): feature_list.append('discover') if features.has('organizations:events-stream', obj, actor=user): feature_list.append('events-stream') if OrganizationOption.objects.filter( organization=obj, key__in=LEGACY_RATE_LIMIT_OPTIONS).exists(): feature_list.append('legacy-rate-limits') 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') if features.has('organizations:event-attachments', obj, actor=user): feature_list.append('event-attachments') experiment_assignments = experiments.all(org=obj) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context['experiments'] = experiment_assignments context['quota'] = { 'maxRate': max_rate[0], 'maxRateInterval': max_rate[1], 'accountLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:account-rate-limit', default=ACCOUNT_RATE_LIMIT_DEFAULT, )), 'projectLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:project-rate-limit', default=PROJECT_RATE_LIMIT_DEFAULT, )), } 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', REQUIRE_SCRUB_DATA_DEFAULT)), 'dataScrubberDefaults': bool( obj.get_option('sentry:require_scrub_defaults', REQUIRE_SCRUB_DEFAULTS_DEFAULT)), 'sensitiveFields': obj.get_option('sentry:sensitive_fields', SENSITIVE_FIELDS_DEFAULT) or [], 'safeFields': obj.get_option('sentry:safe_fields', SAFE_FIELDS_DEFAULT) or [], 'storeCrashReports': bool( obj.get_option('sentry:store_crash_reports', STORE_CRASH_REPORTS_DEFAULT)), 'scrubIPAddresses': bool( obj.get_option('sentry:require_scrub_ip_address', REQUIRE_SCRUB_IP_ADDRESS_DEFAULT)), 'scrapeJavaScript': bool( obj.get_option('sentry:scrape_javascript', SCRAPE_JAVASCRIPT_DEFAULT)), 'trustedRelays': obj.get_option('sentry:trusted-relays', TRUSTED_RELAYS_DEFAULT) or [], }) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) 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