Beispiel #1
0
    def has_object_permission(self, request, view, organization):
        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request,
                organization,
                scopes=request.auth.get_scopes(),
            )

        elif request.auth:
            if request.auth.organization_id == organization.id:
                request.access = access.from_auth(request.auth)
            else:
                request.access = access.DEFAULT

        else:
            request.access = access.from_request(request, organization)

            if auth.is_user_signed_request(request):
                # if the user comes from a signed request
                # we let them pass if sso is enabled
                logger.info(
                    'access.signed-sso-passthrough',
                    extra={
                        'organization_id': organization.id,
                        'user_id': request.user.id,
                    }
                )
            elif request.user.is_authenticated():
                # session auth needs to confirm various permissions
                if self.needs_sso(request, organization):

                    logger.info(
                        'access.must-sso',
                        extra={
                            'organization_id': organization.id,
                            'user_id': request.user.id,
                        }
                    )

                    raise SsoRequired(organization)

                if self.is_not_2fa_compliant(
                        request.user, organization):
                    logger.info(
                        'access.not-2fa-compliant',
                        extra={
                            'organization_id': organization.id,
                            'user_id': request.user.id,
                        }
                    )
                    raise TwoFactorRequired()

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_scope(s) for s in allowed_scopes)
Beispiel #2
0
    def determine_access(self, request, organization):
        from sentry.api.base import logger

        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request,
                organization,
                scopes=request.auth.get_scopes(),
            )

        elif request.auth:
            request.access = access.from_auth(request.auth, organization)

        else:
            request.access = access.from_request(request, organization)

            if auth.is_user_signed_request(request):
                # if the user comes from a signed request
                # we let them pass if sso is enabled
                logger.info(
                    'access.signed-sso-passthrough',
                    extra={
                        'organization_id': organization.id,
                        'user_id': request.user.id,
                    }
                )
            elif request.user.is_authenticated():
                # session auth needs to confirm various permissions
                if self.needs_sso(request, organization):

                    logger.info(
                        'access.must-sso',
                        extra={
                            'organization_id': organization.id,
                            'user_id': request.user.id,
                        }
                    )

                    raise SsoRequired(organization)

                if self.is_not_2fa_compliant(
                        request, organization):
                    logger.info(
                        'access.not-2fa-compliant',
                        extra={
                            'organization_id': organization.id,
                            'user_id': request.user.id,
                        }
                    )
                    raise TwoFactorRequired()
Beispiel #3
0
    def has_object_permission(self, request, view, organization):
        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(request, organization, scopes=request.auth.get_scopes())

        elif request.auth:
            if request.auth is ROOT_KEY:
                return True
            return request.auth.organization_id == organization.id

        else:
            request.access = access.from_request(request, organization)

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_scope(s) for s in allowed_scopes)
Beispiel #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))

        feature_list = []
        if features.has("organizations:events", obj, actor=user):
            feature_list.append("events")
        if features.has("organizations:sso", obj, actor=user):
            feature_list.append("sso")

        if getattr(obj.flags, "allow_joinleave"):
            feature_list.append("open-membership")

        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()
        return context
Beispiel #5
0
    def get_view_response(self, request, group):
        from sentry.models import Event

        self.selected = request.path == self.get_url(group)

        if not self.selected:
            return

        response = self.view(request, group)

        if not response:
            return

        if isinstance(response, HttpResponseRedirect):
            return response

        if not isinstance(response, Response):
            raise NotImplementedError("Use self.render() when returning responses.")

        event = group.get_latest_event() or Event()
        event.group = group

        request.access = access.from_request(request, group.organization)

        return response.respond(
            request,
            {
                "plugin": self,
                "project": group.project,
                "group": group,
                "event": event,
                "can_admin_event": request.access.has_scope("event:write"),
                "can_remove_event": request.access.has_scope("event:delete"),
            },
        )
Beispiel #6
0
    def dispatch(self, request, *args, **kwargs):
        """
        Identical to rest framework's dispatch except we add the ability
        to convert arguments (for common URL params).
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.load_json_body(request)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        if settings.SENTRY_API_RESPONSE_DELAY:
            time.sleep(settings.SENTRY_API_RESPONSE_DELAY / 1000.0)

        origin = request.META.get('HTTP_ORIGIN', 'null')
        # A "null" value should be treated as no Origin for us.
        # See RFC6454 for more information on this behavior.
        if origin == 'null':
            origin = None

        try:
            if origin and request.auth:
                allowed_origins = request.auth.get_allowed_origins()
                if not is_valid_origin(origin, allowed=allowed_origins):
                    response = Response('Invalid origin: %s' %
                                        (origin, ), status=400)
                    self.response = self.finalize_response(
                        request, response, *args, **kwargs)
                    return self.response

            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)

                (args, kwargs) = self.convert_args(request, *args, **kwargs)
                self.args = args
                self.kwargs = kwargs
            else:
                handler = self.http_method_not_allowed

            if getattr(request, 'access', None) is None:
                # setup default access
                request.access = access.from_request(request)

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(request, exc)

        if origin:
            self.add_cors_headers(request, response)

        self.response = self.finalize_response(
            request, response, *args, **kwargs)

        return self.response
    def has_object_permission(self, request, view, organization):
        if request.auth:
            return request.auth.organization_id == organization.id

        request.access = access.from_request(request, organization)
        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_scope(s) for s in allowed_scopes)
Beispiel #8
0
    def get_view_response(self, request, group):
        from sentry.models import Event

        self.selected = request.path == self.get_url(group)

        if not self.selected:
            return

        response = self.view(request, group)

        if not response:
            return

        if isinstance(response, HttpResponseRedirect):
            return response

        if not isinstance(response, Response):
            raise NotImplementedError('Use self.render() when returning responses.')

        event = group.get_latest_event() or Event()
        event.group = group

        request.access = access.from_request(request, group.organization)

        return response.respond(
            request, {
                'plugin': self,
                'project': group.project,
                'group': group,
                'event': event,
                'can_admin_event': request.access.has_scope('event:write'),
                'can_remove_event': request.access.has_scope('event:admin'),
            }
        )
Beispiel #9
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:callsigns', obj, actor=user):
            feature_list.append('callsigns')
        if features.has('organizations:new-tracebacks', obj, actor=user):
            feature_list.append('new-tracebacks')
        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
Beispiel #10
0
    def has_object_permission(self, request, view, project):
        if request.auth:
            return request.auth.organization_id == project.organization_id

        request.access = access.from_request(request, project.organization)

        for scope in self.scope_map.get(request.method, []):
            if request.access.has_team_scope(project.team, scope):
                return True
        return False
Beispiel #11
0
 def build_request(self, user=None, active_superuser=False, **params):
     request = RequestFactory().get('/', params)
     request.session = {}
     if active_superuser:
         request.superuser = MockSuperUser()
     if user is None:
         user = self.user
     request.user = user
     request.access = from_request(request, self.org)
     return request
Beispiel #12
0
    def has_object_permission(self, request, view, team):
        if request.auth:
            if request.auth is ROOT_KEY:
                return True
            return request.auth.organization_id == team.organization_id

        request.access = access.from_request(request, team.organization)

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_team_scope(team, s) for s in allowed_scopes)
Beispiel #13
0
    def has_object_permission(self, request, view, project):
        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request,
                project.organization,
                scopes=request.auth.get_scopes(),
            )

        elif request.auth:
            if request.auth is ROOT_KEY:
                return True
            return request.auth.organization_id == project.organization_id

        else:
            request.access = access.from_request(request, project.organization)

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(
            request.access.has_team_scope(project.team, s)
            for s in allowed_scopes)
Beispiel #14
0
 def test_no_deleted_projects(self):
     self.create_member(organization=self.org, user=self.user, role="owner", teams=[self.team])
     project = self.create_project(
         organization=self.org, status=ObjectStatus.PENDING_DELETION, teams=[self.team]
     )
     request = self.make_request(user=self.proxy_user)
     result = access.from_request(request, self.org)
     assert result.has_project_access(project) is False
     assert result.has_project_membership(project) is False
     assert len(result.projects) == 1
     assert list(result.projects)[0].id == self.project.id
Beispiel #15
0
    def has_object_permission(self, request, view, team):
        if request.auth:
            if self.is_project_key(request):
                return False
            return request.auth.organization_id == team.organization_id

        request.access = access.from_request(request, team.organization)

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(
            request.access.has_team_scope(team, s) for s in allowed_scopes)
Beispiel #16
0
    def test_unlinked_sso_with_no_owners(self):
        user = self.create_user()
        organization = self.create_organization(owner=user)
        self.create_team(organization=organization)
        AuthProvider.objects.create(organization=organization, provider="dummy")
        request = self.make_request(user=user)
        results = [access.from_user(user, organization), access.from_request(request, organization)]

        for result in results:
            assert not result.sso_is_valid
            assert not result.requires_sso
Beispiel #17
0
    def test_superuser_with_organization_without_membership(self):
        request = self.make_request(user=self.superuser, is_superuser=True)
        result = access.from_request(request, self.org)
        assert result.has_permission("test.permission")

        assert not result.requires_sso
        assert result.sso_is_valid

        assert result.teams == frozenset()
        assert result.has_team_access(self.team1)
        assert result.projects == frozenset()
        assert result.has_project_access(self.project1)
Beispiel #18
0
    def has_object_permission(self, request, view, project):
        if request.auth:
            if request.auth is ROOT_KEY:
                return True
            return request.auth.organization_id == project.organization_id

        request.access = access.from_request(request, project.organization)

        for scope in self.scope_map.get(request.method, []):
            if request.access.has_team_scope(project.team, scope):
                return True
        return False
Beispiel #19
0
def get_default_context(request, existing_context=None, team=None):
    from sentry import options
    from sentry.plugins.base import plugins

    context = {
        "URL_PREFIX": options.get("system.url-prefix"),
        "SINGLE_ORGANIZATION": settings.SENTRY_SINGLE_ORGANIZATION,
        "PLUGINS": plugins,
        # Maintain ONPREMISE key for backcompat (plugins?). TBH context could
        # probably be removed entirely: github.com/getsentry/sentry/pull/30970.
        "ONPREMISE": is_self_hosted(),
        "SELF_HOSTED": is_self_hosted(),
    }

    if existing_context:
        if team is None and "team" in existing_context:
            team = existing_context["team"]

        if "project" in existing_context:
            project = existing_context["project"]
        else:
            project = None
    else:
        project = None

    if team:
        organization = team.organization
    elif project:
        organization = project.organization
    else:
        organization = None

    if request:
        if (not existing_context or "TEAM_LIST" not in existing_context) and team:
            context["TEAM_LIST"] = Team.objects.get_for_user(
                organization=team.organization, user=request.user, with_projects=True
            )

        user = request.user
    else:
        user = AnonymousUser()

    if not existing_context or "ACCESS" not in existing_context:
        if request:
            context["ACCESS"] = access.from_request(
                request=request, organization=organization
            ).to_django_context()
        else:
            context["ACCESS"] = access.from_user(
                user=user, organization=organization
            ).to_django_context()

    return context
Beispiel #20
0
def get_default_context(request, existing_context=None, team=None):
    from sentry import options
    from sentry.plugins.base import plugins

    context = {
        "URL_PREFIX": options.get("system.url-prefix"),
        "SINGLE_ORGANIZATION": settings.SENTRY_SINGLE_ORGANIZATION,
        "PLUGINS": plugins,
        "ONPREMISE": settings.SENTRY_ONPREMISE,
    }

    if existing_context:
        if team is None and "team" in existing_context:
            team = existing_context["team"]

        if "project" in existing_context:
            project = existing_context["project"]
        else:
            project = None
    else:
        project = None

    if team:
        organization = team.organization
    elif project:
        organization = project.organization
    else:
        organization = None

    if request:
        if (not existing_context
                or "TEAM_LIST" not in existing_context) and team:
            context["TEAM_LIST"] = Team.objects.get_for_user(
                organization=team.organization,
                user=request.user,
                with_projects=True)

        user = request.user
    else:
        user = AnonymousUser()

    if not existing_context or "ACCESS" not in existing_context:
        if request:
            context["ACCESS"] = access.from_request(
                request=request,
                organization=organization).to_django_context()
        else:
            context["ACCESS"] = access.from_user(
                user=user, organization=organization).to_django_context()

    return context
Beispiel #21
0
    def determine_access(self, request, organization):
        from sentry.api.base import logger

        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request, organization, scopes=request.auth.get_scopes()
            )

        elif request.auth:
            request.access = access.from_auth(request.auth, organization)

        else:
            request.access = access.from_request(request, organization)

            if auth.is_user_signed_request(request):
                # if the user comes from a signed request
                # we let them pass if sso is enabled
                logger.info(
                    "access.signed-sso-passthrough",
                    extra={"organization_id": organization.id, "user_id": request.user.id},
                )
            elif request.user.is_authenticated():
                # session auth needs to confirm various permissions
                if self.needs_sso(request, organization):

                    logger.info(
                        "access.must-sso",
                        extra={"organization_id": organization.id, "user_id": request.user.id},
                    )

                    raise SsoRequired(organization)

                if self.is_not_2fa_compliant(request, organization):
                    logger.info(
                        "access.not-2fa-compliant",
                        extra={"organization_id": organization.id, "user_id": request.user.id},
                    )
                    raise TwoFactorRequired()
Beispiel #22
0
    def has_object_permission(self, request, view, organization):
        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request, organization, scopes=request.auth.get_scopes(),
            )

        elif request.auth:
            if request.auth is ROOT_KEY:
                return True
            return request.auth.organization_id == organization.id

        else:
            request.access = access.from_request(request, organization)
            # session auth needs to confirm various permissions
            if request.user.is_authenticated() and self.needs_sso(request, organization):
                logger.info('access.must-sso', extra={
                    'organization_id': organization.id,
                    'user_id': request.user.id,
                })
                raise NotAuthenticated(detail='Must login via SSO')

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_scope(s) for s in allowed_scopes)
Beispiel #23
0
    def test_has_app_scopes(self):
        app_with_scopes = self.create_sentry_app(name="ScopeyTheApp",
                                                 organization=self.org)
        app_with_scopes.update(scope_list=["team:read", "team:write"])
        self.create_sentry_app_installation(organization=self.org,
                                            slug=app_with_scopes.slug,
                                            user=self.user)

        request = self.make_request(user=app_with_scopes.proxy_user)
        result = access.from_request(request, self.org)
        assert result.scopes == frozenset({"team:read", "team:write"})
        assert result.has_scope("team:read") is True
        assert result.has_scope("team:write") is True
        assert result.has_scope("team:admin") is False
Beispiel #24
0
    def has_object_permission(self, request, view, organization):
        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request, organization, scopes=request.auth.get_scopes(),
            )

        elif request.auth:
            if request.auth is ROOT_KEY:
                return True
            return request.auth.organization_id == organization.id

        else:
            request.access = access.from_request(request, organization)
            # session auth needs to confirm various permissions
            if request.user.is_authenticated() and self.needs_sso(request, organization):
                logger.info('access.must-sso', extra={
                    'organization_id': organization.id,
                    'user_id': request.user.id,
                })
                raise NotAuthenticated(detail='Must login via SSO')

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_scope(s) for s in allowed_scopes)
Beispiel #25
0
    def has_object_permission(self, request, view, organization):
        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request,
                organization,
                scopes=request.auth.get_scopes(),
            )

        elif request.auth:
            return request.auth.organization_id == organization.id

        else:
            request.access = access.from_request(request, organization)

            if auth.is_user_signed_request(request):
                # if the user comes from a signed request
                # we let them pass if sso is enabled
                logger.info(
                    'access.signed-sso-passthrough',
                    extra={
                        'organization_id': organization.id,
                        'user_id': request.user.id,
                    }
                )
            elif request.user.is_authenticated() and self.needs_sso(request, organization):
                # session auth needs to confirm various permissions
                logger.info(
                    'access.must-sso',
                    extra={
                        'organization_id': organization.id,
                        'user_id': request.user.id,
                    }
                )
                raise NotAuthenticated(detail='Must login via SSO')

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_scope(s) for s in allowed_scopes)
Beispiel #26
0
    def has_object_permission(self, request, view, organization):
        if request.user and request.user.is_authenticated() and request.auth:
            request.access = access.from_request(
                request,
                organization,
                scopes=request.auth.get_scopes(),
            )

        elif request.auth:
            return request.auth.organization_id == organization.id

        else:
            request.access = access.from_request(request, organization)

            if auth.is_user_signed_request(request):
                # if the user comes from a signed request
                # we let them pass if sso is enabled
                logger.info(
                    'access.signed-sso-passthrough',
                    extra={
                        'organization_id': organization.id,
                        'user_id': request.user.id,
                    }
                )
            elif request.user.is_authenticated() and self.needs_sso(request, organization):
                # session auth needs to confirm various permissions
                logger.info(
                    'access.must-sso',
                    extra={
                        'organization_id': organization.id,
                        'user_id': request.user.id,
                    }
                )
                raise NotAuthenticated(detail='Must login via SSO')

        allowed_scopes = set(self.scope_map.get(request.method, []))
        return any(request.access.has_scope(s) for s in allowed_scopes)
Beispiel #27
0
    def test_mixed_access(self):
        user = self.create_user()
        organization = self.create_organization(flags=0)  # disable default allow_joinleave
        team = self.create_team(organization=organization)
        team_no_access = self.create_team(organization=organization)
        project = self.create_project(organization=organization, teams=[team])
        project_no_access = self.create_project(organization=organization, teams=[team_no_access])
        self.create_member(organization=organization, user=user, teams=[team])
        request = self.make_request(user=user)
        results = [access.from_user(user, organization), access.from_request(request, organization)]

        for result in results:
            assert result.has_project_access(project)
            assert not result.has_project_access(project_no_access)
            assert not result.has_projects_access([project, project_no_access])
Beispiel #28
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,
        ))

        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):
            feature_list.append('onboarding')

        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
Beispiel #29
0
    def test_unique_projects(self):
        user = self.create_user()
        organization = self.create_organization(owner=self.user)

        team = self.create_team(organization=organization)
        other_team = self.create_team(organization=organization)
        self.create_member(
            organization=organization, user=user, role="owner", teams=[team, other_team]
        )
        project = self.create_project(organization=organization, teams=[team, other_team])

        request = self.make_request(user=user)
        results = [access.from_user(user, organization), access.from_request(request, organization)]

        for result in results:
            assert result.has_project_access(project)
            assert len(result.projects) == 1
Beispiel #30
0
    def test_no_deleted_projects(self):
        user = self.create_user()
        organization = self.create_organization(owner=self.user)

        team = self.create_team(organization=organization)
        self.create_member(organization=organization, user=user, role="owner", teams=[team])
        project = self.create_project(
            organization=organization, status=ObjectStatus.PENDING_DELETION, teams=[team]
        )

        request = self.make_request(user=user)
        results = [access.from_user(user, organization), access.from_request(request, organization)]

        for result in results:
            assert result.has_project_access(project) is True
            assert result.has_project_membership(project) is False
            assert len(result.projects) == 0
Beispiel #31
0
    def test_no_deleted_projects(self):
        self.create_member(organization=self.org,
                           user=self.user,
                           role="owner",
                           teams=[self.team])
        deleted_project = self.create_project(
            organization=self.org,
            status=ObjectStatus.PENDING_DELETION,
            teams=[self.team])
        request = self.make_request(user=self.proxy_user)
        result = access.from_request(request, self.org)
        assert result.has_project_access(deleted_project) is False
        assert result.has_project_membership(deleted_project) is False

        # result.projects also contains other projects created by
        # self.create_sentry_app_installation
        assert deleted_project not in result.projects
        assert self.project in result.projects
Beispiel #32
0
    def test_team_restricted_org_member_access(self):
        user = self.create_user()
        organization = self.create_organization()
        team = self.create_team(organization=organization)
        project = self.create_project(organization=organization, teams=[team])
        member = self.create_member(organization=organization, user=user, teams=[team])
        request = self.make_request(user=user)
        results = [access.from_user(user, organization), access.from_request(request, organization)]

        for result in results:
            assert result.sso_is_valid
            assert not result.requires_sso
            assert result.scopes == member.get_scopes()
            assert result.has_team_access(team)
            assert result.has_team_scope(team, "project:read")
            assert result.has_project_access(project)
            assert result.has_projects_access([project])
            assert result.has_project_scope(project, "project:read")
            assert result.has_project_membership(project)
Beispiel #33
0
    def test_owner_all_teams(self):
        user = self.create_user()
        organization = self.create_organization(owner=self.user)
        member = self.create_member(organization=organization, user=user, role="owner")
        team = self.create_team(organization=organization)
        project = self.create_project(organization=organization, teams=[team])
        request = self.make_request(user=user)
        results = [access.from_user(user, organization), access.from_request(request, organization)]

        for result in results:
            assert result.sso_is_valid
            assert not result.requires_sso
            assert result.scopes == member.get_scopes()
            assert result.has_team_access(team)
            assert result.has_team_scope(team, "project:read")
            assert result.has_project_access(project)
            assert result.has_projects_access([project])
            assert result.has_project_scope(project, "project:read")
            # owners should have access but not membership
            assert result.has_project_membership(project) is False
Beispiel #34
0
    def test_superuser_with_organization_without_membership(self):
        org = self.create_organization()
        AuthProvider.objects.create(organization=org)
        team = self.create_team(organization=org)
        project = self.create_project(organization=org, teams=[team])

        user = self.create_user(is_superuser=True)
        UserPermission.objects.create(user=user, permission="test.permission")

        request = self.make_request(user=user, is_superuser=True)
        result = access.from_request(request, org)
        assert result.has_permission("test.permission")

        assert not result.requires_sso
        assert result.sso_is_valid

        assert result.teams == frozenset({team})
        assert result.has_team_access(team)
        assert result.projects == frozenset({project})
        assert result.has_project_access(project)
Beispiel #35
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,
        ))

        feature_list = []
        if features.has('organizations:sso', obj, actor=user):
            feature_list.append('sso')
        if features.has('organizations:my-issues', obj, actor=user):
            feature_list.append('my-issues')

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

        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()
        return context
Beispiel #36
0
    def test_no_deleted_teams(self):
        user = self.create_user()
        organization = self.create_organization(owner=self.user)

        team = self.create_team(organization=organization)
        deleted_team = self.create_team(organization=organization,
                                        status=TeamStatus.PENDING_DELETION)
        self.create_member(organization=organization,
                           user=user,
                           role="owner",
                           teams=[team, deleted_team])

        request = self.make_request(user=user)
        results = [
            access.from_user(user, organization),
            access.from_request(request, organization)
        ]

        for result in results:
            assert result.has_team_access(team) is True
            assert result.has_team_access(deleted_team) is False
            assert result.teams == frozenset({team})
Beispiel #37
0
    def test_member_no_teams_open_membership(self):
        user = self.create_user()
        organization = self.create_organization(
            owner=self.user, flags=Organization.flags.allow_joinleave
        )
        member = self.create_member(organization=organization, user=user, role="member", teams=())
        team = self.create_team(organization=organization)
        project = self.create_project(organization=organization, teams=[team])

        request = self.make_request(user=user)
        results = [access.from_user(user, organization), access.from_request(request, organization)]

        for result in results:
            assert result.sso_is_valid
            assert not result.requires_sso
            assert result.scopes == member.get_scopes()
            assert result.has_team_access(team)
            assert result.has_team_scope(team, "project:read")
            assert result.has_project_access(project)
            assert result.has_projects_access([project])
            assert result.has_project_scope(project, "project:read")
            assert not result.has_project_membership(project)
Beispiel #38
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))

        feature_list = []
        if features.has("organizations:sso", obj, actor=user):
            feature_list.append("sso")

        if getattr(obj.flags, "allow_joinleave"):
            feature_list.append("open-membership")

        context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user)
        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()
        return context
Beispiel #39
0
    def get_view_response(self, request, group):
        from sentry.models import Event

        self.selected = request.path == self.get_url(group)

        if not self.selected:
            return

        response = self.view(request, group)

        if not response:
            return

        if isinstance(response, HttpResponseRedirect):
            return response

        if not isinstance(response, Response):
            raise NotImplementedError(
                "Use self.render() when returning responses.")

        event = group.get_latest_event() or Event()
        event.group = group

        request.access = access.from_request(request, group.organization)

        return response.respond(
            request,
            {
                "plugin": self,
                "project": group.project,
                "group": group,
                "event": event,
                "can_admin_event": request.access.has_scope("event:write"),
                "can_remove_event": request.access.has_scope("event:admin"),
            },
        )
Beispiel #40
0
def get_default_context(request, existing_context=None, team=None):
    from sentry import options
    from sentry.plugins import plugins

    context = {
        'EVENTS_PER_PAGE': EVENTS_PER_PAGE,
        'URL_PREFIX': options.get('system.url-prefix'),
        'SINGLE_ORGANIZATION': settings.SENTRY_SINGLE_ORGANIZATION,
        'PLUGINS': plugins,
        'ALLOWED_HOSTS': list(settings.ALLOWED_HOSTS),
    }

    if existing_context:
        if team is None and 'team' in existing_context:
            team = existing_context['team']

        if 'project' in existing_context:
            project = existing_context['project']
        else:
            project = None
    else:
        project = None

    if team:
        organization = team.organization
    elif project:
        organization = project.organization
    else:
        organization = None

    if request:
        context.update({
            'request': request,
        })

        if (not existing_context or 'TEAM_LIST' not in existing_context) and team:
            context['TEAM_LIST'] = Team.objects.get_for_user(
                organization=team.organization,
                user=request.user,
                with_projects=True,
            )

        user = request.user
    else:
        user = AnonymousUser()

    if organization:
        context['selectedOrganization'] = serialize(organization, user)
    if team:
        context['selectedTeam'] = serialize(team, user)
    if project:
        context['selectedProject'] = serialize(project, user)

    if not existing_context or 'ACCESS' not in existing_context:
        if request:
            context['ACCESS'] = access.from_request(
                request=request,
                organization=organization,
            ).to_django_context()
        else:
            context['ACCESS'] = access.from_user(
                user=user,
                organization=organization,
            ).to_django_context()

    return context
Beispiel #41
0
    def dispatch(self, request, *args, **kwargs):
        """
        Identical to rest framework's dispatch except we add the ability
        to convert arguments (for common URL params).
        """
        with sentry_sdk.start_span(op="base.dispatch.setup", description=type(self).__name__):
            self.args = args
            self.kwargs = kwargs
            request = self.initialize_request(request, *args, **kwargs)
            self.load_json_body(request)
            self.request = request
            self.headers = self.default_response_headers  # deprecate?

        # Tags that will ultimately flow into the metrics backend at the end of
        # the request (happens via middleware/stats.py).
        request._metric_tags = {}

        if settings.SENTRY_API_RESPONSE_DELAY:
            with sentry_sdk.start_span(
                op="base.dispatch.sleep", description=type(self).__name__,
            ) as span:
                span.set_data("SENTRY_API_RESPONSE_DELAY", settings.SENTRY_API_RESPONSE_DELAY)
                time.sleep(settings.SENTRY_API_RESPONSE_DELAY / 1000.0)

        origin = request.META.get("HTTP_ORIGIN", "null")
        # A "null" value should be treated as no Origin for us.
        # See RFC6454 for more information on this behavior.
        if origin == "null":
            origin = None

        try:
            with sentry_sdk.start_span(op="base.dispatch.request", description=type(self).__name__):
                if origin and request.auth:
                    allowed_origins = request.auth.get_allowed_origins()
                    if not is_valid_origin(origin, allowed=allowed_origins):
                        response = Response("Invalid origin: %s" % (origin,), status=400)
                        self.response = self.finalize_response(request, response, *args, **kwargs)
                        return self.response

                self.initial(request, *args, **kwargs)

                # Get the appropriate handler method
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

                    (args, kwargs) = self.convert_args(request, *args, **kwargs)
                    self.args = args
                    self.kwargs = kwargs
                else:
                    handler = self.http_method_not_allowed

                if getattr(request, "access", None) is None:
                    # setup default access
                    request.access = access.from_request(request)

            with sentry_sdk.start_span(
                op="base.dispatch.execute",
                description="{}.{}".format(type(self).__name__, handler.__name__),
            ):
                response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(request, exc)

        if origin:
            self.add_cors_headers(request, response)

        self.response = self.finalize_response(request, response, *args, **kwargs)

        return self.response
Beispiel #42
0
    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
Beispiel #43
0
 def get_access(self, request, organization, *args, **kwargs):
     if organization is None:
         return access.DEFAULT
     return access.from_request(request, organization)
Beispiel #44
0
    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
Beispiel #45
0
    def dispatch(self, request, *args, **kwargs):
        """
        Identical to rest framework's dispatch except we add the ability
        to convert arguments (for common URL params).
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        if settings.SENTRY_API_RESPONSE_DELAY:
            time.sleep(settings.SENTRY_API_RESPONSE_DELAY / 1000.0)

        origin = request.META.get('HTTP_ORIGIN', 'null')
        # A "null" value should be treated as no Origin for us.
        # See RFC6454 for more information on this behavior.
        if origin == 'null':
            origin = None

        try:
            if origin and request.auth:
                allowed_origins = request.auth.get_allowed_origins()
                if not is_valid_origin(origin, allowed=allowed_origins):
                    response = Response('Invalid origin: %s' %
                                        (origin, ), status=400)
                    self.response = self.finalize_response(
                        request, response, *args, **kwargs)
                    return self.response

            self.initial(request, *args, **kwargs)

            if getattr(request, 'user', None) and request.user.is_authenticated():
                raven.user_context({
                    'id': request.user.id,
                    'username': request.user.username,
                    'email': request.user.email,
                })

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)

                (args, kwargs) = self.convert_args(request, *args, **kwargs)
                self.args = args
                self.kwargs = kwargs
            else:
                handler = self.http_method_not_allowed

            if getattr(request, 'access', None) is None:
                # setup default access
                request.access = access.from_request(request)

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(request, exc)

        if origin:
            self.add_cors_headers(request, response)

        self.response = self.finalize_response(
            request, response, *args, **kwargs)

        return self.response
Beispiel #46
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 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)
        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),
                '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
Beispiel #47
0
def get_default_context(request, existing_context=None, team=None):
    from sentry import options
    from sentry.plugins import plugins

    context = {
        'URL_PREFIX': options.get('system.url-prefix'),
        'SINGLE_ORGANIZATION': settings.SENTRY_SINGLE_ORGANIZATION,
        'PLUGINS': plugins,
        'ONPREMISE': settings.SENTRY_ONPREMISE,
    }

    if existing_context:
        if team is None and 'team' in existing_context:
            team = existing_context['team']

        if 'project' in existing_context:
            project = existing_context['project']
        else:
            project = None
    else:
        project = None

    if team:
        organization = team.organization
    elif project:
        organization = project.organization
    else:
        organization = None

    if request:
        context.update({
            'request': request,
        })

        if (not existing_context
                or 'TEAM_LIST' not in existing_context) and team:
            context['TEAM_LIST'] = Team.objects.get_for_user(
                organization=team.organization,
                user=request.user,
                with_projects=True,
            )

        user = request.user
    else:
        user = AnonymousUser()

    if organization:
        context['selectedOrganization'] = serialize(organization, user)
    if team:
        context['selectedTeam'] = serialize(team, user)
    if project:
        context['selectedProject'] = serialize(project, user)

    if not existing_context or 'ACCESS' not in existing_context:
        if request:
            context['ACCESS'] = access.from_request(
                request=request,
                organization=organization,
            ).to_django_context()
        else:
            context['ACCESS'] = access.from_user(
                user=user,
                organization=organization,
            ).to_django_context()

    return context
Beispiel #48
0
    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
Beispiel #49
0
    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 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
Beispiel #50
0
    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'):
            feature_list.add('open-membership')
        if not getattr(obj.flags, 'disable_shared_issues'):
            feature_list.add('shared-issues')
        if getattr(obj.flags, 'require_2fa'):
            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