def get(self, request): status = request.GET.get('status') if status == 'published': queryset = SentryApp.objects.filter(status=SentryAppStatus.PUBLISHED) elif status == 'unpublished': if is_active_superuser(request): queryset = SentryApp.objects.filter( status=SentryAppStatus.UNPUBLISHED ) else: queryset = SentryApp.objects.filter( status=SentryAppStatus.UNPUBLISHED, owner__in=request.user.get_orgs(), ) else: if is_active_superuser(request): queryset = SentryApp.objects.all() else: queryset = SentryApp.objects.filter(status=SentryAppStatus.PUBLISHED) return self.paginate( request=request, queryset=queryset, order_by='-date_added', paginator_cls=OffsetPaginator, on_results=lambda x: serialize(x, request.user), )
def get(self, request, *args, **kwargs): next_uri = self.get_next_uri(request, *args, **kwargs) if request.user.is_authenticated(): # if the user is a superuser, but not 'superuser authenticated' # we allow them to re-authenticate to gain superuser status if not request.user.is_superuser or is_active_superuser(request): return self.handle_authenticated(request, *args, **kwargs) request.session.set_test_cookie() # we always reset the state on GET so you dont end up at an odd location auth.initiate_login(request, next_uri) # Single org mode -- send them to the org-specific handler if settings.SENTRY_SINGLE_ORGANIZATION: org = Organization.get_default() next_uri = reverse('sentry-auth-organization', args=[org.slug]) return HttpResponseRedirect(next_uri) session_expired = 'session_expired' in request.COOKIES if session_expired: messages.add_message(request, messages.WARNING, WARN_SESSION_EXPIRED) response = self.handle_basic_auth(request, *args, **kwargs) if session_expired: response.delete_cookie('session_expired') return response
def get_allowed_projects(self, request, organization): has_valid_api_key = False if isinstance(request.auth, ApiKey): if request.auth.organization_id != organization.id: return [] has_valid_api_key = request.auth.has_scope('project:releases') or \ request.auth.has_scope('project:write') if not (has_valid_api_key or request.user.is_authenticated()): return [] if has_valid_api_key or is_active_superuser(request) or organization.flags.allow_joinleave: allowed_teams = Team.objects.filter(organization=organization).values_list( 'id', flat=True ) else: allowed_teams = OrganizationMemberTeam.objects.filter( organizationmember__user=request.user, team__organization_id=organization.id, ).values_list( 'team_id', flat=True ) return Project.objects.filter( id__in=ProjectTeam.objects.filter( team_id__in=allowed_teams, ).values_list('project_id', flat=True) )
def wrapped(request, *args, **kwargs): if not is_active_superuser(request): if request.user.is_superuser: auth.initiate_login(request, next_url=request.get_full_path()) return HttpResponseRedirect(auth.get_login_url()) return render_to_response('sentry/missing_permissions.html', {}, request, status=400) return func(request, *args, **kwargs)
def post(self, request): if not (is_active_superuser(request) and request.access.has_permission('broadcasts.admin')): return self.respond(status=401) validator = AdminBroadcastValidator(data=request.DATA) if not validator.is_valid(): return self.respond(validator.errors, status=400) result = validator.object with transaction.atomic(): broadcast = Broadcast.objects.create( title=result['title'], message=result['message'], link=result['link'], is_active=result.get('isActive') or False, date_expires=result.get('expiresAt'), ) logger.info('broadcasts.create', extra={ 'ip_address': request.META['REMOTE_ADDR'], 'user_id': request.user.id, 'broadcast_id': broadcast.id, }) if result.get('hasSeen'): try: with transaction.atomic(): BroadcastSeen.objects.create( broadcast=broadcast, user=request.user, ) except IntegrityError: pass return self.respond(self._serialize_objects(broadcast, request))
def get_projects( self, request, organization, force_global_perms=False, include_all_accessible=False, ): """ Determines which project ids to filter the endpoint by. If a list of project ids is passed in via the `project` querystring argument then validate that these projects can be accessed. If not passed, then return all project ids that the user can access within this organization. :param request: :param organization: Organization to fetch projects for :param force_global_perms: Permission override. Allows subclasses to perform their own validation and allow the user to access any project in the organization. This is a hack to support the old `request.auth.has_scope` way of checking permissions, don't use it for anything else, we plan to remove this once we remove uses of `auth.has_scope`. :param include_all_accessible: Whether to factor the organization allow_joinleave flag into permission checks. We should ideally standardize how this is used and remove this parameter. :return: A list of project ids, or raises PermissionDenied. """ project_ids = set(map(int, request.GET.getlist('project'))) requested_projects = project_ids.copy() user = getattr(request, 'user', None) qs = Project.objects.filter( organization=organization, status=ProjectStatus.VISIBLE, ) if project_ids: qs = qs.filter(id__in=project_ids) if force_global_perms: projects = list(qs) else: if ( user and is_active_superuser(request) or requested_projects or include_all_accessible ): func = request.access.has_project_access else: func = request.access.has_project_membership projects = [p for p in qs if func(p)] project_ids = set(p.id for p in projects) if requested_projects and project_ids != requested_projects: raise PermissionDenied return projects
def has_object_permission(self, request, view, project): result = super(ProjectPermission, self).has_object_permission(request, view, project.organization) if not result: return result if project.teams.exists(): return any( has_team_permission(request, team, self.scope_map) for team in project.teams.all() ) elif request.user.is_authenticated(): # this is only for team-less projects if is_active_superuser(request): return True try: role = OrganizationMember.objects.filter( organization=project.organization, user=request.user, ).values_list('role', flat=True).get() except OrganizationMember.DoesNotExist: # this should probably never happen? return False return roles.get(role).is_global elif hasattr(request.auth, 'project_id') and project.id == request.auth.project_id: return True return False
def from_request(request, organization, scopes=None): if not organization: return DEFAULT if is_active_superuser(request): # we special case superuser so that if they're a member of the org # they must still follow SSO checks, but they gain global access try: member = OrganizationMember.objects.get( user=request.user, organization=organization, ) except OrganizationMember.DoesNotExist: requires_sso, sso_is_valid = False, True else: requires_sso, sso_is_valid = _sso_params(member) team_list = list(organization.team_set.all()) return Access( scopes=scopes if scopes is not None else settings.SENTRY_SCOPES, is_active=True, teams=team_list, memberships=team_list, sso_is_valid=sso_is_valid, requires_sso=requires_sso, ) return from_user(request.user, organization, scopes=scopes)
def _serialize_objects(self, items, request): if is_active_superuser(request): serializer_cls = AdminBroadcastSerializer else: serializer_cls = BroadcastSerializer return serialize(items, request.user, serializer=serializer_cls())
def serialize(self, obj, attrs, user): from sentry.mediators.service_hooks.creator import consolidate_events data = { 'name': obj.name, 'slug': obj.slug, 'author': obj.author, 'scopes': obj.get_scopes(), 'events': consolidate_events(obj.events), 'status': obj.get_status_display(), 'schema': obj.schema, 'uuid': obj.uuid, 'webhookUrl': obj.webhook_url, 'redirectUrl': obj.redirect_url, 'isAlertable': obj.is_alertable, 'overview': obj.overview, } if is_active_superuser(env.request) or ( hasattr(user, 'get_orgs') and obj.owner in user.get_orgs() ): data.update({ 'clientId': obj.application.client_id, 'clientSecret': obj.application.client_secret, 'owner': { 'id': obj.owner.id, 'slug': obj.owner.slug, }, }) return data
def handle(self, request, organization): try: auth_provider = AuthProvider.objects.get( organization=organization, ) except AuthProvider.DoesNotExist: pass else: provider = auth_provider.get_provider() requires_feature = provider.required_feature # Provider is not enabled # Allow superusers to edit and disable SSO for orgs that # downgrade plans and can no longer access the feature if requires_feature and not features.has( requires_feature, organization, actor=request.user ) and not is_active_superuser(request): home_url = organization.get_url() messages.add_message(request, messages.ERROR, ERR_NO_SSO) return HttpResponseRedirect(home_url) return self.handle_existing_provider( request=request, organization=organization, auth_provider=auth_provider, ) if request.method == 'POST': provider_key = request.POST.get('provider') if not manager.exists(provider_key): raise ValueError(u'Provider not found: {}'.format(provider_key)) helper = AuthHelper( request=request, organization=organization, provider_key=provider_key, flow=AuthHelper.FLOW_SETUP_PROVIDER, ) feature = helper.provider.required_feature if feature and not features.has(feature, organization, actor=request.user): return HttpResponse('Provider is not enabled', status=401) if request.POST.get('init'): helper.init_pipeline() if not helper.pipeline_is_valid(): return helper.error('Something unexpected happened during authentication.') # render first time setup view return helper.current_step() # Otherwise user is in bad state since frontend/react should handle this case return HttpResponseRedirect( organization.get_url() )
def can(self, request): if 'prof' not in request.GET: return False if settings.DEBUG: return True if is_active_superuser(request): return True return False
def has_object_permission(self, request, view, user=None): if user is None: user = request.user if request.user == user: return True if request.auth: return False if is_active_superuser(request): return True return False
def get_allowed_roles(self, request, organization, member=None): can_admin = request.access.has_scope('member:admin') allowed_roles = [] if can_admin and not is_active_superuser(request): acting_member = OrganizationMember.objects.get( user=request.user, organization=organization, ) if member and roles.get(acting_member.role).priority < roles.get(member.role).priority: can_admin = False else: allowed_roles = [ r for r in roles.get_all() if r.priority <= roles.get(acting_member.role).priority ] can_admin = bool(allowed_roles) elif is_active_superuser(request): allowed_roles = roles.get_all() return (can_admin, allowed_roles, )
def _can_access(self, request, member): # TODO(dcramer): ideally org owners/admins could perform these actions if is_active_superuser(request): return True if not request.user.is_authenticated(): return False if request.user.id == member.user_id: return True return False
def _get_identities(self, item_list, user): if not (env.request and is_active_superuser(env.request)): item_list = [x for x in item_list if x == user] queryset = AuthIdentity.objects.filter( user__in=item_list, ).select_related('auth_provider', 'auth_provider__organization') results = {i.id: [] for i in item_list} for item in queryset: results[item.user_id].append(item) return results
def _get_broadcast(self, request, broadcast_id): if is_active_superuser(request) and request.access.has_permission('broadcasts.admin'): queryset = Broadcast.objects.all() else: queryset = Broadcast.objects.filter( Q(date_expires__isnull=True) | Q(date_expires__gt=timezone.now()), is_active=True, ) try: return queryset.get(id=broadcast_id) except Broadcast.DoesNotExist: raise ResourceDoesNotExist
def show_toolbar_for_request(self, request): # This avoids touching user session, which means we avoid # setting `Vary: Cookie` as a response header which will # break HTTP caching entirely. if request.path_info.startswith(settings.ANONYMOUS_STATIC_PREFIXES): return if not settings.SENTRY_DEBUGGER: return False if not is_active_superuser(request): return False if 'text/html' not in request.META.get('HTTP_ACCEPT', '*/*'): return False return True
def convert_args(self, request, organization_slug, *args, **kwargs): if is_active_superuser(request): organizations = Organization.objects.all() else: organizations = request.user.get_orgs() try: organization = organizations.get(slug=organization_slug) except Organization.DoesNotExist: raise Http404 self.check_object_permissions(request, organization) kwargs['organization'] = organization return (args, kwargs)
def put(self, request, user): """ Update Account Appearance options ````````````````````````````````` Update account appearance options. Only supplied values are updated. :pparam string user_id: user id :param string language: language preference :param string stacktrace_order: One of -1 (default), 1 (most recent call last), 2 (most recent call first). :param string timezone: timezone option :param clock_24_hours boolean: use 24 hour clock :auth: required """ if is_active_superuser(request): serializer_cls = AdminUserSerializer else: serializer_cls = UserSerializer serializer = serializer_cls(user, data=request.DATA, partial=True) serializer_options = UserOptionsSerializer( data=request.DATA.get('options', {}), partial=True) # This serializer should NOT include privileged fields e.g. password if not serializer.is_valid() or not serializer_options.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # map API keys to keys in model key_map = { 'language': 'language', 'timezone': 'timezone', 'stacktraceOrder': 'stacktrace_order', 'clock24Hours': 'clock_24_hours', 'seenReleaseBroadcast': 'seen_release_broadcast', } options_result = serializer_options.object for key in key_map: if key in options_result: UserOption.objects.set_value( user=user, key=key_map.get(key, key), value=options_result.get(key), ) user = serializer.save() return Response(serialize(user, request.user, DetailedUserSerializer()))
def delete(self, request, organization, member_id): try: om = self._get_member(request, organization, member_id) except OrganizationMember.DoesNotExist: raise ResourceDoesNotExist if request.user.is_authenticated() and not is_active_superuser(request): try: acting_member = OrganizationMember.objects.get( organization=organization, user=request.user, ) except OrganizationMember.DoesNotExist: return Response({'detail': ERR_INSUFFICIENT_ROLE}, status=400) else: if acting_member != om: if not request.access.has_scope('member:admin'): return Response({'detail': ERR_INSUFFICIENT_SCOPE}, status=400) elif not roles.can_manage(acting_member.role, om.role): return Response({'detail': ERR_INSUFFICIENT_ROLE}, status=400) # TODO(dcramer): do we even need this check? elif not request.access.has_scope('member:admin'): return Response({'detail': ERR_INSUFFICIENT_SCOPE}, status=400) if self._is_only_owner(om): return Response({'detail': ERR_ONLY_OWNER}, status=403) audit_data = om.get_audit_log_data() with transaction.atomic(): AuthIdentity.objects.filter( user=om.user, auth_provider__organization=organization, ).delete() om.delete() self.create_audit_entry( request=request, organization=organization, target_object=om.id, target_user=om.user, event=AuditLogEntryEvent.MEMBER_REMOVE, data=audit_data, ) return Response(status=204)
def has_object_permission(self, request, view, installation): if not hasattr(request, 'user') or not request.user: return False self.determine_access(request, installation.organization) if is_active_superuser(request): return True if installation.organization not in request.user.get_orgs(): raise Http404 return ensure_scoped_permission( request, self.scope_map.get(request.method), )
def has_object_permission(self, request, view, sentry_app): if not hasattr(request, 'user') or not request.user: return False self.determine_access(request, sentry_app.owner) if is_active_superuser(request): return True # User must be in the Org who owns the app. if sentry_app.owner not in request.user.get_orgs(): raise Http404 return ensure_scoped_permission( request, self._scopes_for_sentry_app(sentry_app).get(request.method), )
def has_object_permission(self, request, view, organization): if not hasattr(request, 'user') or not request.user: return False self.determine_access(request, organization) if is_active_superuser(request): return True # User must be a part of the Org they're trying to create the app in. if organization not in request.user.get_orgs(): raise Http404 return ensure_scoped_permission( request, self.scope_map.get(request.method), )
def is_member_disabled_from_limit(request, organization): user = request.user # never limit sentry apps if getattr(user, "is_sentry_app", False): return False # don't limit super users if is_active_superuser(request): return False # must be a simple user at this point try: member = get_cached_organization_member(user.id, organization.id) except OrganizationMember.DoesNotExist: # if org member doesn't exist, we should be getting an auth error later return False else: return member.flags["member-limit:restricted"]
def serialize(self, obj, attrs, user, access): from sentry.mediators.service_hooks.creator import consolidate_events data = { "name": obj.name, "slug": obj.slug, "author": obj.author, "scopes": obj.get_scopes(), "events": consolidate_events(obj.events), "status": obj.get_status_display(), "schema": obj.schema, "uuid": obj.uuid, "webhookUrl": obj.webhook_url, "redirectUrl": obj.redirect_url, "isAlertable": obj.is_alertable, "verifyInstall": obj.verify_install, "overview": obj.overview, "allowedOrigins": obj.application.get_allowed_origins(), } data["featureData"] = [] if obj.status != SentryAppStatus.INTERNAL: features = IntegrationFeature.objects.filter(sentry_app_id=obj.id) data["featureData"] = map(lambda x: serialize(x, user), features) if obj.status == SentryAppStatus.PUBLISHED and obj.date_published: data.update({"datePublished": obj.date_published}) if (env.request and is_active_superuser(env.request)) or (hasattr( user, "get_orgs") and obj.owner in user.get_orgs()): client_secret = (obj.application.client_secret if obj.show_auth_info(access) else MASKED_VALUE) data.update({ "clientId": obj.application.client_id, "clientSecret": client_secret, "owner": { "id": obj.owner.id, "slug": obj.owner.slug }, }) return data
def from_request(request, organization=None, scopes=None): if not organization: return from_user(request.user, organization=organization, scopes=scopes) if getattr(request.user, "is_sentry_app", False): return _from_sentry_app(request.user, organization=organization) if is_active_superuser(request): role = None # we special case superuser so that if they're a member of the org # they must still follow SSO checks, but they gain global access try: member = OrganizationMember.objects.get(user=request.user, organization=organization) except OrganizationMember.DoesNotExist: requires_sso, sso_is_valid = False, True else: requires_sso, sso_is_valid = _sso_params(member) role = member.role team_list = () project_list = () return Access( scopes=scopes if scopes is not None else settings.SENTRY_SCOPES, is_active=True, organization_id=organization.id if organization else None, teams=team_list, projects=project_list, sso_is_valid=sso_is_valid, requires_sso=requires_sso, has_global_access=True, permissions=UserPermission.for_user(request.user.id), role=role, ) # TODO: from_auth does not take scopes as a parameter so this fails for anon user if hasattr(request, "auth") and not request.user.is_authenticated(): return from_auth(request.auth, scopes=scopes) return from_user(request.user, organization, scopes=scopes)
def get_attrs( self, item_list: Sequence[Team], user: User, **kwargs: Any) -> MutableMapping[Team, MutableMapping[str, Any]]: request = env.request org_ids = {t.organization_id for t in item_list} org_roles = get_org_roles(org_ids, user) member_totals = get_member_totals(item_list, user) memberships = get_team_memberships(item_list, user) access_requests = get_access_requests(item_list, user) avatars = { a.team_id: a for a in TeamAvatar.objects.filter(team__in=item_list) } is_superuser = request and is_active_superuser( request) and request.user == user result: MutableMapping[Team, MutableMapping[str, Any]] = {} for team in item_list: is_member = team.id in memberships org_role = org_roles.get(team.organization_id) if is_member: has_access = True elif is_superuser: has_access = True elif team.organization.flags.allow_joinleave: has_access = True elif org_role and roles.get(org_role).is_global: has_access = True else: has_access = False result[team] = { "pending_request": team.id in access_requests, "is_member": is_member, "has_access": has_access, "avatar": avatars.get(team.id), "member_count": member_totals.get(team.id, 0), } return result
def get(self, request): if not is_active_superuser(request): return Response() results = status_checks.check_all() return Response( { 'problems': [ { 'id': md5_text(problem.message).hexdigest(), 'message': problem.message, 'severity': problem.severity, 'url': problem.url, } for problem in sort_by_severity(itertools.chain.from_iterable(results.values())) ], 'healthy': {type(check).__name__: not problems for check, problems in results.items()}, } )
def put(self, request, user): if is_active_superuser(request): serializer_cls = AdminUserSerializer else: serializer_cls = UserSerializer serializer = serializer_cls(user, data=request.DATA, partial=True) if serializer.is_valid(): user = serializer.save() options = request.DATA.get('options', {}) if options.get('seenReleaseBroadcast'): UserOption.objects.set_value( user=user, key='seen_release_broadcast', value=options.get('seenReleaseBroadcast'), ) return Response(serialize(user, request.user)) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def put(self, request, user): if is_active_superuser(request): serializer_cls = AdminUserSerializer else: serializer_cls = UserSerializer serializer = serializer_cls(user, data=request.DATA, partial=True) if serializer.is_valid(): user = serializer.save() options = request.DATA.get('options', {}) if options.get('seenReleaseBroadcast'): UserOption.objects.set_value( user=user, key='seen_release_broadcast', value=options.get('seenReleaseBroadcast'), ) return Response(serialize(user, request.user)) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def has_object_permission(self, request, view, installation): if not hasattr(request, 'user') or not request.user: return False self.determine_access(request, installation.organization) if is_active_superuser(request): return True # if user is an app, make sure it's for that same app if request.user.is_sentry_app: return request.user == installation.sentry_app.proxy_user if installation.organization not in request.user.get_orgs(): raise Http404 return ensure_scoped_permission( request, self.scope_map.get(request.method), )
def _get_projects_by_id( self, project_ids, request, organization, force_global_perms=False, include_all_accessible=False, ): qs = Project.objects.filter(organization=organization, status=ProjectStatus.VISIBLE) user = getattr(request, "user", None) # A project_id of -1 means 'all projects I have access to' # While no project_ids means 'all projects I am a member of'. if project_ids == ALL_ACCESS_PROJECTS: include_all_accessible = True project_ids = set() requested_projects = project_ids.copy() if project_ids: qs = qs.filter(id__in=project_ids) if force_global_perms: projects = list(qs) else: if ( user and is_active_superuser(request) or requested_projects or include_all_accessible ): func = request.access.has_project_access else: func = request.access.has_project_membership projects = [p for p in qs if func(p)] project_ids = set(p.id for p in projects) if requested_projects and project_ids != requested_projects: raise PermissionDenied return projects
def from_request(request, organization=None, scopes=None): if not organization: return from_user(request.user, organization=organization, scopes=scopes) if getattr(request.user, 'is_sentry_app', False): return from_sentry_app(request.user, organization=organization) if is_active_superuser(request): # we special case superuser so that if they're a member of the org # they must still follow SSO checks, but they gain global access try: member = OrganizationMember.objects.get( user=request.user, organization=organization, ) except OrganizationMember.DoesNotExist: requires_sso, sso_is_valid = False, True else: requires_sso, sso_is_valid = _sso_params(member) team_list = () project_list = () return Access( scopes=scopes if scopes is not None else settings.SENTRY_SCOPES, is_active=True, organization_id=organization.id if organization else None, teams=team_list, projects=project_list, sso_is_valid=sso_is_valid, requires_sso=requires_sso, has_global_access=True, permissions=UserPermission.for_user(request.user.id), ) if hasattr(request, 'auth') and not request.user.is_authenticated(): return from_auth(request.auth, scopes=scopes) return from_user(request.user, organization, scopes=scopes)
def from_request(request, organization=None, scopes=None): if not organization: return from_user(request.user, organization=organization, scopes=scopes) if getattr(request.user, 'is_sentry_app', False): return from_sentry_app(request.user, organization=organization) if is_active_superuser(request): # we special case superuser so that if they're a member of the org # they must still follow SSO checks, but they gain global access try: member = OrganizationMember.objects.get( user=request.user, organization=organization, ) except OrganizationMember.DoesNotExist: requires_sso, sso_is_valid = False, True else: requires_sso, sso_is_valid = _sso_params(member) team_list = () project_list = () return Access( scopes=scopes if scopes is not None else settings.SENTRY_SCOPES, is_active=True, organization_id=organization.id if organization else None, teams=team_list, projects=project_list, sso_is_valid=sso_is_valid, requires_sso=requires_sso, open_access_policy=True, permissions=UserPermission.for_user(request.user.id), ) if hasattr(request, 'auth') and not request.user.is_authenticated(): return from_auth(request.auth, scopes=scopes) return from_user(request.user, organization, scopes=scopes)
def get(self, request: Request) -> Response: if not is_active_superuser(request): return Response() results = status_checks.check_all() return Response( { "problems": [ { "id": md5_text(problem.message).hexdigest(), "message": problem.message, "severity": problem.severity, "url": problem.url, } for problem in sort_by_severity(itertools.chain.from_iterable(results.values())) ], "healthy": { type(check).__name__: not problems for check, problems in results.items() }, } )
def _is_authorized(self, user, organization_id): # If user is not logged in and member of the organization, # do not return the permalink which contains private information i.e. org name. request = env.request if request and is_active_superuser(request) and request.user == user: return True # If user is a sentry_app then it's a proxy user meaning we can't do a org lookup via `get_orgs()` # because the user isn't an org member. Instead we can use the auth token and the installation # it's associated with to find out what organization the token has access to. if ( request and getattr(request.user, "is_sentry_app", False) and isinstance(request.auth, ApiToken) ): if SentryAppInstallationToken.objects.has_organization_access( request.auth, organization_id ): return True return user.is_authenticated and user.get_orgs().filter(id=organization_id).exists()
def _can_access(self, request, member, organization): if is_active_superuser(request): return True if not request.user.is_authenticated(): return False if request.user.id == member.user_id: return True acting_member = OrganizationMember.objects.get( organization=organization, user__id=request.user.id, user__is_active=True, ) if roles.get(acting_member.role).is_global and \ roles.can_manage(acting_member.role, member.role): return True return False
def is_member_disabled_from_limit(request, organization): user = request.user # never limit sentry apps if getattr(user, "is_sentry_app", False): return False # don't limit super users if is_active_superuser(request): return False # must be a simple user at this point try: member = get_cached_organization_member(user.id, organization.id) except OrganizationMember.DoesNotExist: # should never happen but if it does, don't block auth # but send error to logs/Sentry logger.error("is_member_disabled_from_limit.member_missing") return False else: return member.flags["member-limit:restricted"]
def _can_access(self, request, member, organization): if is_active_superuser(request): return True if not request.user.is_authenticated(): return False if request.user.id == member.user_id: return True acting_member = OrganizationMember.objects.get( organization=organization, user__id=request.user.id, user__is_active=True, ) if roles.get(acting_member.role).is_global and \ roles.can_manage(acting_member.role, member.role): return True return False
def convert_args(self, request, organization_slug, *args, **kwargs): try: organization = Organization.objects.get_from_cache(slug=organization_slug) except Organization.DoesNotExist: raise ResourceDoesNotExist self.check_object_permissions(request, organization) bind_organization_context(organization) request._request.organization = organization # Track the 'active' organization when the request came from # a cookie based agent (react app) # Never track any org (regardless of whether the user does or doesn't have # membership in that org) when the user is in active superuser mode if request.auth is None and request.user and not is_active_superuser(request): request.session["activeorg"] = organization.slug kwargs["organization"] = organization return (args, kwargs)
def get_allowed_projects(self, request, organization): has_valid_api_key = False if isinstance(request.auth, ApiKey): if request.auth.organization_id != organization.id: return [] has_valid_api_key = request.auth.has_scope('project:releases') or \ request.auth.has_scope('project:write') if not (has_valid_api_key or request.user.is_authenticated()): return [] if has_valid_api_key or is_active_superuser( request) or organization.flags.allow_joinleave: allowed_teams = Team.objects.filter( organization=organization).values_list('id', flat=True) else: allowed_teams = OrganizationMemberTeam.objects.filter( organizationmember__user=request.user, team__organization_id=organization.id, ).values_list('team_id', flat=True) return Project.objects.filter(team_id__in=allowed_teams)
def get(self, request, organization): """ List your Teams In the Current Organization ``````````````````````````````````````````` Return a list of the teams available to the authenticated session and with the supplied organization. If the user is a super user, then all teams within the organization are returned. """ if is_active_superuser(request): # retrieve all teams within the organization queryset = Team.objects.filter( organization=organization, status=TeamStatus.VISIBLE).order_by("slug") return Response( serialize(list(queryset), request.user, TeamWithProjectsSerializer())) else: return Response( serialize(list(request.access.teams), request.user, TeamWithProjectsSerializer()))
def get_attrs(self, item_list, user): request = env.request org_ids = set([t.organization_id for t in item_list]) org_roles = get_org_roles(org_ids, user) member_totals = get_member_totals(item_list, user) memberships = get_team_memberships(item_list, user) access_requests = get_access_requests(item_list, user) avatars = { a.team_id: a for a in TeamAvatar.objects.filter(team__in=item_list) } is_superuser = (request and is_active_superuser(request) and request.user == user) result = {} for team in item_list: is_member = team.id in memberships org_role = org_roles.get(team.organization_id) if is_member: has_access = True elif is_superuser: has_access = True elif team.organization.flags.allow_joinleave: has_access = True elif org_role and roles.get(org_role).is_global: has_access = True else: has_access = False result[team] = { 'pending_request': team.id in access_requests, 'is_member': is_member, 'has_access': has_access, 'avatar': avatars.get(team.id), 'member_count': member_totals.get(team.id, 0), } return result
def from_request(request, organization: Organization = None, scopes: Optional[Iterable[str]] = None) -> Access: is_superuser = is_active_superuser(request) if not organization: return from_user(request.user, organization=organization, scopes=scopes, is_superuser=is_superuser) if getattr(request.user, "is_sentry_app", False): return _from_sentry_app(request.user, organization=organization) if is_superuser: member = None # we special case superuser so that if they're a member of the org # they must still follow SSO checks, but they gain global access try: member = get_cached_organization_member(request.user.id, organization.id) except OrganizationMember.DoesNotExist: requires_sso, sso_is_valid = False, True else: requires_sso, sso_is_valid = _sso_params(member) return OrganizationGlobalAccess( organization=organization, member=member, scopes=scopes if scopes is not None else settings.SENTRY_SCOPES, sso_is_valid=sso_is_valid, requires_sso=requires_sso, permissions=get_permissions_for_user(request.user.id), ) # TODO: from_auth does not take scopes as a parameter so this fails for anon user if hasattr(request, "auth") and not request.user.is_authenticated: return from_auth(request.auth, scopes=scopes) return from_user(request.user, organization, scopes=scopes)
def serialize(self, obj, attrs, user): from sentry.mediators.service_hooks.creator import consolidate_events data = { 'name': obj.name, 'slug': obj.slug, 'author': obj.author, 'scopes': obj.get_scopes(), 'events': consolidate_events(obj.events), 'status': obj.get_status_display(), 'schema': obj.schema, 'uuid': obj.uuid, 'webhookUrl': obj.webhook_url, 'redirectUrl': obj.redirect_url, 'isAlertable': obj.is_alertable, 'overview': obj.overview, } if is_active_superuser( env.request) or (hasattr(user, 'get_orgs') and obj.owner in user.get_orgs()): if obj.is_internal: install = obj.installations.first() data.update({ 'installation': { 'uuid': install.uuid, }, 'token': install.api_token.token, }) else: data.update({ 'clientId': obj.application.client_id, 'clientSecret': obj.application.client_secret, 'owner': { 'id': obj.owner.id, 'slug': obj.owner.slug, }, }) return data
def get_attrs(self, item_list, user): request = env.request if user.is_authenticated(): memberships = frozenset( OrganizationMemberTeam.objects.filter( organizationmember__user=user, team__in=item_list, ).values_list('team', flat=True) ) else: memberships = frozenset() if user.is_authenticated(): access_requests = frozenset( OrganizationAccessRequest.objects.filter( team__in=item_list, member__user=user, ).values_list('team', flat=True) ) else: access_requests = frozenset() is_superuser = (request and is_active_superuser(request) and request.user == user) result = {} for team in item_list: is_member = team.id in memberships if is_member: has_access = True elif is_superuser: has_access = True elif team.organization.flags.allow_joinleave: has_access = True else: has_access = False result[team] = { 'pending_request': team.id in access_requests, 'is_member': is_member, 'has_access': has_access, } return result
def get_access_by_project(self, item_list, user): request = env.request project_teams = list( ProjectTeam.objects.filter( project__in=item_list, ).select_related('team') ) project_team_map = defaultdict(list) for pt in project_teams: project_team_map[pt.project_id].append(pt.team) team_memberships = get_team_memberships([pt.team for pt in project_teams], user) org_roles = get_org_roles([i.organization_id for i in item_list], user) is_superuser = (request and is_active_superuser(request) and request.user == user) result = {} for project in item_list: is_member = any( t.id in team_memberships for t in project_team_map.get(project.id, []) ) org_role = org_roles.get(project.organization_id) if is_member: has_access = True elif is_superuser: has_access = True elif project.organization.flags.allow_joinleave: has_access = True elif org_role and roles.get(org_role).is_global: has_access = True else: has_access = False result[project] = { 'is_member': is_member, 'has_access': has_access, } return result
def get_attrs(self, item_list, user): request = env.request memberships = get_team_memberships(item_list, user) if user.is_authenticated(): access_requests = frozenset( OrganizationAccessRequest.objects.filter( team__in=item_list, member__user=user, ).values_list('team', flat=True) ) else: access_requests = frozenset() org_roles = get_org_roles([t.organization_id for t in item_list], user) avatars = {a.team_id: a for a in TeamAvatar.objects.filter(team__in=item_list)} is_superuser = (request and is_active_superuser(request) and request.user == user) result = {} for team in item_list: is_member = team.id in memberships org_role = org_roles.get(team.organization_id) if is_member: has_access = True elif is_superuser: has_access = True elif team.organization.flags.allow_joinleave: has_access = True elif org_role and roles.get(org_role).is_global: has_access = True else: has_access = False result[team] = { 'pending_request': team.id in access_requests, 'is_member': is_member, 'has_access': has_access, 'avatar': avatars.get(team.id), } return result
def get_attrs(self, item_list, user): request = env.request memberships = get_team_memberships(item_list, user) if user.is_authenticated(): access_requests = frozenset( OrganizationAccessRequest.objects.filter( team__in=item_list, member__user=user, ).values_list('team', flat=True) ) else: access_requests = frozenset() org_roles = get_org_roles([t.organization_id for t in item_list], user) avatars = {a.team_id: a for a in TeamAvatar.objects.filter(team__in=item_list)} is_superuser = (request and is_active_superuser(request) and request.user == user) result = {} for team in item_list: is_member = team.id in memberships org_role = org_roles.get(team.organization_id) if is_member: has_access = True elif is_superuser: has_access = True elif team.organization.flags.allow_joinleave: has_access = True elif org_role and roles.get(org_role).is_global: has_access = True else: has_access = False result[team] = { 'pending_request': team.id in access_requests, 'is_member': is_member, 'has_access': has_access, 'avatar': avatars.get(team.id), } return result
def _can_delete(self, request, member, organization, team_slug): """ User can remove a member from a team: * If they are an active superuser * If they are removing their own membership * If they are a team admin or have global write access """ if is_active_superuser(request): return True if not request.user.is_authenticated(): return False if request.user.id == member.user_id: return True if self._can_admin_team(request, organization, team_slug): return True return False
def get_access_by_project(self, item_list, user): request = env.request project_teams = list( ProjectTeam.objects.filter( project__in=item_list, ).select_related('team') ) project_team_map = defaultdict(list) for pt in project_teams: project_team_map[pt.project_id].append(pt.team) team_memberships = get_team_memberships([pt.team for pt in project_teams], user) org_roles = get_org_roles([i.organization_id for i in item_list], user) is_superuser = (request and is_active_superuser(request) and request.user == user) result = {} for project in item_list: is_member = any( t.id in team_memberships for t in project_team_map.get(project.id, []) ) org_role = org_roles.get(project.organization_id) if is_member: has_access = True elif is_superuser: has_access = True elif project.organization.flags.allow_joinleave: has_access = True elif org_role and roles.get(org_role).is_global: has_access = True else: has_access = False result[project] = { 'is_member': is_member, 'has_access': has_access, } return result
def post(self, request): if not (is_active_superuser(request) and request.access.has_permission('broadcasts.admin')): return self.respond(status=401) validator = AdminBroadcastValidator(data=request.data) if not validator.is_valid(): return self.respond(validator.errors, status=400) result = validator.validated_data with transaction.atomic(): broadcast = Broadcast.objects.create( title=result['title'], message=result['message'], link=result['link'], cta=result['cta'], is_active=result.get('isActive') or False, date_expires=result.get('dateExpires'), ) logger.info('broadcasts.create', extra={ 'ip_address': request.META['REMOTE_ADDR'], 'user_id': request.user.id, 'broadcast_id': broadcast.id, }) if result.get('hasSeen'): try: with transaction.atomic(): BroadcastSeen.objects.create( broadcast=broadcast, user=request.user, ) except IntegrityError: pass return self.respond(self._serialize_objects(broadcast, request))
def post(self, request): if not (is_active_superuser(request) and request.access.has_permission("broadcasts.admin")): return self.respond(status=401) validator = AdminBroadcastValidator(data=request.data) if not validator.is_valid(): return self.respond(validator.errors, status=400) result = validator.validated_data with transaction.atomic(): broadcast = Broadcast.objects.create( title=result["title"], message=result["message"], link=result["link"], cta=result["cta"], is_active=result.get("isActive") or False, date_expires=result.get("dateExpires"), ) logger.info( "broadcasts.create", extra={ "ip_address": request.META["REMOTE_ADDR"], "user_id": request.user.id, "broadcast_id": broadcast.id, }, ) if result.get("hasSeen"): try: with transaction.atomic(): BroadcastSeen.objects.create(broadcast=broadcast, user=request.user) except IntegrityError: pass return self.respond(self._serialize_objects(broadcast, request))
def has_object_permission(self, request, view, sentry_app): if not hasattr(request, "user") or not request.user: return False self.determine_access(request, sentry_app.owner) if is_active_superuser(request): return True # if app is unpublished, user must be in the Org who owns the app. if not sentry_app.is_published: if sentry_app.owner not in request.user.get_orgs(): raise Http404 # TODO(meredith): make a better way to allow for public # endpoints. we can't use ensure_scoped_permission now # that the public endpoint isn't denoted by '()' if sentry_app.is_published and request.method == "GET": return True return ensure_scoped_permission( request, self._scopes_for_sentry_app(sentry_app).get(request.method))
def get_access_by_project( projects: Sequence[Project], user: User) -> MutableMapping[Project, MutableMapping[str, Any]]: request = env.request project_teams = list( ProjectTeam.objects.filter( project__in=projects).select_related("team")) project_team_map = defaultdict(list) for pt in project_teams: project_team_map[pt.project_id].append(pt.team) team_memberships = get_team_memberships([pt.team for pt in project_teams], user) org_roles = get_org_roles({i.organization_id for i in projects}, user) is_superuser = request and is_active_superuser( request) and request.user == user result = {} for project in projects: is_member = any(t.id in team_memberships for t in project_team_map.get(project.id, [])) org_role = org_roles.get(project.organization_id) if is_member: has_access = True elif is_superuser: has_access = True elif project.organization.flags.allow_joinleave: has_access = True elif org_role and roles.get(org_role).is_global: has_access = True else: has_access = False result[project] = {"is_member": is_member, "has_access": has_access} return result
def get_project_ids(self, request, organization): project_ids = set(map(int, request.GET.getlist('project'))) before = project_ids.copy() if is_active_superuser(request): # Superusers can query any projects within the organization qs = Project.objects.filter( organization=organization, status=ProjectStatus.VISIBLE, ) else: # Anyone else needs membership of the project qs = Project.objects.filter( organization=organization, teams__in=OrganizationMemberTeam.objects.filter( organizationmember__user=request.user, organizationmember__organization=organization, ).values_list('team'), status=ProjectStatus.VISIBLE, ) # If no project's are passed through querystring, we want to # return all projects, otherwise, limit to the passed in ones if project_ids: qs = qs.filter(id__in=project_ids) project_ids = set(qs.values_list('id', flat=True)) if before and project_ids != before: raise PermissionDenied if not project_ids: return # Make sure project_ids is now a list, otherwise # snuba isn't happy with it being a set return list(project_ids)
def _get_permalink(self, obj, user): # If user is not logged in and member of the organization, # do not return the permalink which contains private information i.e. org name. request = env.request is_superuser = request and is_active_superuser( request) and request.user == user # If user is a sentry_app then it's a proxy user meaning we can't do a org lookup via `get_orgs()` # because the user isn't an org member. Instead we can use the auth token and the installation # it's associated with to find out what organization the token has access to. is_valid_sentryapp = False if (request and getattr(request.user, "is_sentry_app", False) and isinstance(request.auth, ApiToken)): is_valid_sentryapp = SentryAppInstallationToken.has_organization_access( request.auth, obj.organization) if (is_superuser or is_valid_sentryapp or (user.is_authenticated() and user.get_orgs().filter(id=obj.organization.id).exists())): with sentry_sdk.start_span( op="GroupSerializerBase.serialize.permalink.build"): return obj.get_absolute_url() else: return None
def delete(self, request, project, user_hash): """ Delete an Event User ```````````````````````````````` Delete an event's user. :pparam string organization_slug: the slug of the organization. :pparam string project_slug: the slug of the project. :pparam string user_hash: the user hash. """ if is_active_superuser(request): try: euser = EventUser.objects.get(project_id=project.id, hash=user_hash) except EventUser.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) euser.delete() return Response(status=status.HTTP_200_OK) else: return Response(status=status.HTTP_403_FORBIDDEN)
def has_object_permission(self, request, view, project): result = super().has_object_permission(request, view, project.organization) if not result: return result if project.teams.exists(): return any( has_team_permission(request, team, self.scope_map) for team in project.teams.all() ) elif is_system_auth(request.auth): return True elif request.user and request.user.is_authenticated: # this is only for team-less projects if is_active_superuser(request): return True elif request.user.is_sentry_app: return SentryApp.objects.check_project_permission_for_sentry_app_user( request.user, project ) try: role = ( OrganizationMember.objects.filter( organization=project.organization, user=request.user ) .values_list("role", flat=True) .get() ) except OrganizationMember.DoesNotExist: # this should probably never happen? return False return roles.get(role).is_global elif hasattr(request.auth, "project_id") and project.id == request.auth.project_id: return True return False