def get_allowed_roles(self, request, organization, member=None): from sentry.auth.superuser import is_active_superuser # Django 1.9 setup issue from sentry.models import OrganizationMember # Django 1.9 setup issue 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 handle(self, request, organization, member_id): try: member = OrganizationMember.objects.get( Q(user__is_active=True) | Q(user__isnull=True), organization=organization, id=member_id, ) except OrganizationMember.DoesNotExist: return self.redirect(get_login_url()) if request.POST.get('op') == 'reinvite' and member.is_pending: return self.resend_invite(request, organization, member) elif request.POST.get('op') == 'regenerate' and member.is_pending: return self.resend_invite(request, organization, member, regen=True) can_admin = request.access.has_scope('member:delete') if can_admin and not request.is_superuser(): acting_member = OrganizationMember.objects.get( user=request.user, organization=organization, ) if 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 request.is_superuser(): allowed_roles = roles.get_all() if member.user == request.user or not can_admin: return self.view_member(request, organization, member) form = self.get_form(request, member, allowed_roles) if form.is_valid(): member = form.save(request.user, organization, request.META['REMOTE_ADDR']) messages.add_message(request, messages.SUCCESS, _('Your changes were saved.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, member.id]) return self.redirect(redirect) context = { 'member': member, 'form': form, 'invite_link': member.get_invite_link(), 'role_list': [ (r, r in allowed_roles) for r in roles.get_all() ] } return self.respond('sentry/organization-member-settings.html', context)
def handle(self, request, organization, member_id): try: member = OrganizationMember.objects.get( Q(user__is_active=True) | Q(user__isnull=True), organization=organization, id=member_id, ) except OrganizationMember.DoesNotExist: return self.redirect(get_login_url()) if request.POST.get('op') == 'reinvite' and member.is_pending: return self.resend_invite(request, organization, member) can_admin = request.access.has_scope('member:delete') if can_admin and not request.is_superuser(): acting_member = OrganizationMember.objects.get( user=request.user, organization=organization, ) if 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 request.is_superuser(): allowed_roles = roles.get_all() if member.user == request.user or not can_admin: return self.view_member(request, organization, member) form = self.get_form(request, member, allowed_roles) if form.is_valid(): member = form.save(request.user, organization, request.META['REMOTE_ADDR']) messages.add_message(request, messages.SUCCESS, _('Your changes were saved.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, member.id]) return self.redirect(redirect) context = { 'member': member, 'form': form, 'role_list': [ (r, r in allowed_roles) for r in roles.get_all() ] } return self.respond('sentry/organization-member-settings.html', context)
def get_allowed_roles(self, request, organization, member=None): can_admin = request.access.has_scope("member:delete") allowed_roles = [] if can_admin and not request.is_superuser(): 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 request.is_superuser(): allowed_roles = roles.get_all() return (can_admin, allowed_roles)
def handle(self, request, organization): form = self.get_form(request, organization) if form.is_valid(): om, created = form.save(request.user, organization, request.META['REMOTE_ADDR']) if created: messages.add_message(request, messages.SUCCESS, _('The organization member was added.')) else: messages.add_message( request, messages.INFO, _('The organization member already exists.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, om.id]) return HttpResponseRedirect(redirect) context = { 'form': form, 'is_invite': settings.SENTRY_ENABLE_INVITES, 'role_list': roles.get_all(), } return self.respond('sentry/create-organization-member.html', context)
def determine_member_recipients(self) -> Iterable[OrganizationMember]: members: Iterable[ OrganizationMember] = OrganizationMember.objects.get_contactable_members_for_org( self.organization.id).filter( role__in=(r.id for r in roles.get_all() if r.has_scope("member:write")), ) return members
def post(self, request, project): """ Request to Add CODEOWNERS to a Project ```````````````````````````````````` :pparam string organization_slug: the slug of the organization the member will belong to :pparam string project_slug: the slug of the project :auth: required """ requester_name = request.user.get_display_name() integrations_roles = [ r.id for r in roles.get_all() if r.has_scope("org:integrations") ] recipients = OrganizationMember.objects.get_contactable_members_for_org( project.organization.id).filter(role__in=integrations_roles) for recipient in recipients: msg = MessageBuilder(**get_codeowners_request_builder_args( project, recipient, requester_name)) email = recipient.get_email() logger.info("send_email", extra={ "organization_id": project.organization.id, "email": email }) msg.send_async([email]) return self.respond(status=202)
def handle(self, request, organization): form = self.get_form(request, organization) if form.is_valid(): om, created = form.save(request.user, organization, request.META['REMOTE_ADDR']) if created: messages.add_message(request, messages.SUCCESS, _('The organization member was added.')) member_invited.send(member=om, user=request.user, sender=self) else: messages.add_message(request, messages.INFO, _('The organization member already exists.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, om.id]) return HttpResponseRedirect(redirect) context = { 'form': form, 'is_invite': settings.SENTRY_ENABLE_INVITES, 'role_list': roles.get_all(), } return self.respond('sentry/create-organization-member.html', context)
def post(self, request, organization): """ Add a invite request to Organization ```````````````````````````````````` Creates an invite request given an email and sugested role / teams. :pparam string organization_slug: the slug of the organization the member will belong to :param string email: the email address to invite :param string role: the suggested role of the new member :param array teams: the suggested slugs of the teams the member should belong to. :auth: required """ if not features.has("organizations:invite-members", organization, actor=request.user): return Response( { "organization": "Your organization is not allowed to invite members" }, status=403) serializer = OrganizationMemberSerializer( data=request.data, context={ "organization": organization, "allowed_roles": roles.get_all() }, ) if not serializer.is_valid(): return Response(serializer.errors, status=400) result = serializer.validated_data with transaction.atomic(): om = OrganizationMember.objects.create( organization=organization, email=result["email"], role=result["role"], inviter=request.user, invite_status=InviteStatus.REQUESTED_TO_BE_INVITED.value, ) if result["teams"]: lock = locks.get(u"org:member:{}".format(om.id), duration=5) with TimedRetryPolicy(10)(lock.acquire): save_team_assignments(om, result["teams"]) self.create_audit_entry( request=request, organization_id=organization.id, target_object=om.id, data=om.get_audit_log_data(), event=AuditLogEntryEvent.INVITE_REQUEST_ADD, ) return Response(serialize(om), status=201)
def send_invite_request_notification_email(member_id): try: om = OrganizationMember.objects.select_related( "inviter", "organization").get(id=member_id) except OrganizationMember.DoesNotExist: return link_args = {"organization_slug": om.organization.slug} context = { "email": om.email, "organization_name": om.organization.name, "pending_requests_link": absolute_uri( reverse("sentry-organization-members-requests", kwargs=link_args)), } if om.requested_to_join: email_args = { "template": "sentry/emails/organization-join-request.txt", "html_template": "sentry/emails/organization-join-request.html", } context["settings_link"] = absolute_uri( reverse("sentry-organization-settings", args=[om.organization.slug])) elif om.requested_to_be_invited: email_args = { "template": "sentry/emails/organization-invite-request.txt", "html_template": "sentry/emails/organization-invite-request.html", } context["inviter_name"] = om.inviter.get_salutation_name else: raise RuntimeError("This member is not pending invitation") recipients = OrganizationMember.objects.select_related("user").filter( organization_id=om.organization_id, user__isnull=False, invite_status=InviteStatus.APPROVED.value, role__in=(r.id for r in roles.get_all() if r.has_scope("member:write")), ) msg = MessageBuilder( subject=f"Access request to {om.organization.name}", type="organization.invite-request", context=context, **email_args, ) for recipient in recipients: try: msg.send_async([recipient.get_email()]) except Exception as e: logger = get_logger(name="sentry.mail") logger.exception(e)
def handle(self, request): try: integration = get_integration_from_request(request, 'jira') except AtlassianConnectValidationError: return self.get_response( {'error_message': 'Unable to verify installation.'}) except ExpiredSignatureError: return self.get_response({'refresh_required': True}) if not request.user.is_authenticated(): return self.get_response({ 'login_required': True, 'login_url': absolute_uri(reverse('sentry-login')), }) organizations = list(request.user.get_orgs().filter( id__in=OrganizationMember.objects.filter( role__in=[r.id for r in roles.get_all() if r.is_global], user=request.user, ).values('organization'), )) form = JiraConfigForm(organizations, request.POST) if request.method == 'GET' or not form.is_valid(): active_orgs = OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=organizations).values_list('organization_id', flat=True) form = JiraConfigForm(organizations, initial={'organizations': active_orgs}) return self.get_response({ 'form': form, 'organizations': organizations }) enabled_orgs = [ o for o in organizations if o.id in form.cleaned_data['organizations'] ] disabled_orgs = list(set(organizations) - set(enabled_orgs)) # Remove Jira integrations not in the set of enabled organizations OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=disabled_orgs, ).delete() # Ensure all enabled integrations. for org in enabled_orgs: integration.add_organization(org, request.user) return self.get_response({'form': form, 'completed': True})
def view_member(self, request, organization, member, all_teams): context = { 'member': member, 'enabled_teams': set(member.teams.all()), 'all_teams': all_teams, 'role_list': roles.get_all(), } return self.respond('sentry/organization-member-details.html', context)
def get_allowed_roles_to_invite(self): """ Return a list of roles which that member could invite Must check if member member has member:admin first before checking """ return [ r for r in roles.get_all() if r.priority <= roles.get(self.role).priority ]
def send_request_notification_email(self): from sentry.utils.email import MessageBuilder link_args = {"organization_slug": self.organization.slug} context = { "email": self.email, "inviter": self.inviter, "organization": self.organization, "organization_link": absolute_uri( reverse("sentry-organization-index", args=[self.organization.slug])), "pending_requests_link": absolute_uri( reverse("sentry-organization-members-requests", kwargs=link_args)), } if self.requested_to_join: email_args = { "template": "sentry/emails/organization-join-request.txt", "html_template": "sentry/emails/organization-join-request.html", } elif self.requested_to_be_invited: email_args = { "template": "sentry/emails/organization-invite-request.txt", "html_template": "sentry/emails/organization-invite-request.html", } else: raise RuntimeError("This member is not pending invitation") recipients = OrganizationMember.objects.select_related("user").filter( organization_id=self.organization_id, user__isnull=False, invite_status=InviteStatus.APPROVED.value, role__in=(r.id for r in roles.get_all() if r.has_scope("member:write")), ) msg = MessageBuilder(subject="Access request to %s" % (self.organization.name, ), type="organization.invite-request", context=context, **email_args) for recipient in recipients: try: msg.send_async([recipient.get_email()]) except Exception as e: logger = get_logger(name="sentry.mail") logger.exception(e)
def view_member(self, request, organization, member): context = { 'member': member, 'enabled_teams': set(member.teams.all()), 'all_teams': Team.objects.filter(organization=organization, ), 'role_list': roles.get_all(), } return self.respond('sentry/organization-member-details.html', context)
def get_allowed_roles(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 = member or 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 handle(self, request): try: integration = get_integration_from_request(request, "jira") except AtlassianConnectValidationError: return self.get_response({"error_message": "Unable to verify installation."}) except ExpiredSignatureError: return self.get_response({"refresh_required": True}) if not request.user.is_authenticated(): parsed_user_agent = user_agent_parser.ParseUserAgent( request.META.get("HTTP_USER_AGENT", "") ) # not enabling cross site cookies seems to be a common problem with Safari # as a result, there is a Safari specific link to instructions when is_safari=true is_safari = parsed_user_agent.get("family") == "Safari" return self.get_response( { "login_required": True, "is_safari": is_safari, "login_url": absolute_uri(reverse("sentry-login")), } ) organizations = list( request.user.get_orgs().filter( id__in=OrganizationMember.objects.filter( role__in=[r.id for r in roles.get_all() if r.is_global], user=request.user ).values("organization") ) ) form = JiraConfigForm(organizations, request.POST) if request.method == "GET" or not form.is_valid(): active_orgs = OrganizationIntegration.objects.filter( integration__provider="jira", integration=integration, organization__in=organizations, ).values_list("organization_id", flat=True) form = JiraConfigForm(organizations, initial={"organizations": active_orgs}) return self.get_response({"form": form, "organizations": organizations}) enabled_orgs = [o for o in organizations if o.id in form.cleaned_data["organizations"]] disabled_orgs = list(set(organizations) - set(enabled_orgs)) # Remove Jira integrations not in the set of enabled organizations OrganizationIntegration.objects.filter( integration__provider="jira", integration=integration, organization__in=disabled_orgs ).delete() # Ensure all enabled integrations. for org in enabled_orgs: integration.add_organization(org, request.user) return self.get_response({"form": form, "completed": True})
def handle(self, request): try: integration = get_integration_from_request(request, "jira") except AtlassianConnectValidationError: return self.get_response( {"error_message": "Unable to verify installation."}) except ExpiredSignatureError: return self.get_response({"refresh_required": True}) if not request.user.is_authenticated(): return self.get_response({ "login_required": True, "login_url": absolute_uri(reverse("sentry-login")) }) organizations = list(request.user.get_orgs().filter( id__in=OrganizationMember.objects.filter( role__in=[r.id for r in roles.get_all() if r.is_global], user=request.user).values("organization"))) form = JiraConfigForm(organizations, request.POST) if request.method == "GET" or not form.is_valid(): active_orgs = OrganizationIntegration.objects.filter( integration__provider="jira", integration=integration, organization__in=organizations, ).values_list("organization_id", flat=True) form = JiraConfigForm(organizations, initial={"organizations": active_orgs}) return self.get_response({ "form": form, "organizations": organizations }) enabled_orgs = [ o for o in organizations if o.id in form.cleaned_data["organizations"] ] disabled_orgs = list(set(organizations) - set(enabled_orgs)) # Remove Jira integrations not in the set of enabled organizations OrganizationIntegration.objects.filter( integration__provider="jira", integration=integration, organization__in=disabled_orgs).delete() # Ensure all enabled integrations. for org in enabled_orgs: integration.add_organization(org, request.user) return self.get_response({"form": form, "completed": True})
def get_allowed_roles(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 = member or 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 get_allowed_roles(self, request, organization, member=None): can_admin = request.access.has_scope('member:delete') allowed_roles = [] if can_admin and not request.is_superuser(): 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 request.is_superuser(): allowed_roles = roles.get_all() return (can_admin, allowed_roles,)
def _serialize_member(self, member, request, allowed_roles=None): context = serialize(member, serializer=OrganizationMemberWithTeamsSerializer()) if request.access.has_scope('member:admin'): context['invite_link'] = member.get_invite_link() context['roles'] = serialize(roles.get_all(), serializer=RoleSerializer(), allowed_roles=allowed_roles) return context
def _serialize_member(self, member, request, allowed_roles=None): context = serialize(member, serializer=OrganizationMemberWithTeamsSerializer()) if request.access.has_scope("member:admin"): context["invite_link"] = member.get_invite_link() context["user"] = serialize(member.user, request.user, DetailedUserSerializer()) context["isOnlyOwner"] = self.is_only_owner(member) context["roles"] = serialize( roles.get_all(), serializer=RoleSerializer(), allowed_roles=allowed_roles ) return context
def _serialize_member(self, member, request, allowed_roles=None): context = serialize( member, serializer=OrganizationMemberWithTeamsSerializer() ) if request.access.has_scope('member:admin'): context['invite_link'] = member.get_invite_link() context['roles'] = serialize( roles.get_all(), serializer=RoleSerializer(), allowed_roles=allowed_roles) return context
def handle(self, request, organization, member_id): try: member = OrganizationMember.objects.get( Q(user__is_active=True) | Q(user__isnull=True), organization=organization, id=member_id, ) except OrganizationMember.DoesNotExist: return self.redirect(auth.get_login_url()) if request.POST.get('op') == 'reinvite' and member.is_pending: return self.resend_invite(request, organization, member) elif request.POST.get('op') == 'regenerate' and member.is_pending: return self.resend_invite(request, organization, member, regen=True) can_admin, allowed_roles = self.get_allowed_roles( request, organization, member) all_teams = Team.objects.filter(organization=organization, status=TeamStatus.VISIBLE) if member.user == request.user or not can_admin: return self.view_member(request, organization, member, all_teams) form = self.get_form(request, member, all_teams, allowed_roles) if form.is_valid(): member = form.save(request.user, organization, request.META['REMOTE_ADDR']) messages.add_message(request, messages.SUCCESS, _('Your changes were saved.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, member.id]) return self.redirect(redirect) context = { 'member': member, 'form': form, 'invite_link': member.get_invite_link(), 'role_list': [(r, r in allowed_roles) for r in roles.get_all()], 'all_teams': all_teams } return self.respond('sentry/organization-member-settings.html', context)
def handle(self, request, organization, member_id): try: member = OrganizationMember.objects.get( Q(user__is_active=True) | Q(user__isnull=True), organization=organization, id=member_id, ) except OrganizationMember.DoesNotExist: return self.redirect(auth.get_login_url()) if request.POST.get('op') == 'reinvite' and member.is_pending: return self.resend_invite(request, organization, member) elif request.POST.get('op') == 'regenerate' and member.is_pending: return self.resend_invite(request, organization, member, regen=True) can_admin, allowed_roles = self.get_allowed_roles(request, organization, member) all_teams = Team.objects.filter( organization=organization, status=TeamStatus.VISIBLE ) if member.user == request.user or not can_admin: return self.view_member(request, organization, member, all_teams) form = self.get_form(request, member, all_teams, allowed_roles) if form.is_valid(): member = form.save(request.user, organization, request.META['REMOTE_ADDR']) messages.add_message(request, messages.SUCCESS, _('Your changes were saved.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, member.id]) return self.redirect(redirect) context = { 'member': member, 'form': form, 'invite_link': member.get_invite_link(), 'role_list': [ (r, r in allowed_roles) for r in roles.get_all() ], 'all_teams': all_teams } return self.respond('sentry/organization-member-settings.html', context)
def handle(self, request): try: integration = get_integration_from_request(request, 'jira') except AtlassianConnectValidationError: return self.get_response({'error_message': 'Unable to verify installation.'}) except ExpiredSignatureError: return self.get_response({'refresh_required': True}) if not request.user.is_authenticated(): return self.get_response({ 'login_required': True, 'login_url': absolute_uri(reverse('sentry-login')), }) organizations = list(request.user.get_orgs().filter( id__in=OrganizationMember.objects.filter( role__in=[r.id for r in roles.get_all() if r.is_global], user=request.user, ).values('organization'), )) form = JiraConfigForm(organizations, request.POST) if request.method == 'GET' or not form.is_valid(): active_orgs = OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=organizations ).values_list('organization_id', flat=True) form = JiraConfigForm(organizations, initial={'organizations': active_orgs}) return self.get_response({'form': form, 'organizations': organizations}) enabled_orgs = [o for o in organizations if o.id in form.cleaned_data['organizations']] disabled_orgs = list(set(organizations) - set(enabled_orgs)) # Remove Jira integrations not in the set of enabled organizations OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=disabled_orgs, ).delete() # Ensure all enabled integrations. for org in enabled_orgs: integration.add_organization(org, request.user) return self.get_response({'form': form, 'completed': True})
def handle(self, request): try: integration = get_integration_from_request(request, 'jira') except AtlassianConnectValidationError: return self.get_response( {'error_message': 'Unable to verify installation.'}) organizations = request.user.get_orgs().filter( id__in=OrganizationMember.objects.filter( role__in=[r.id for r in roles.get_all() if r.is_global], user=request.user, ).values('organization'), ) form = JiraConfigForm(organizations, request.POST) if request.method == 'GET' or not form.is_valid(): active_orgs = OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=organizations).values_list('organization_id', flat=True) form = JiraConfigForm(organizations, initial={'organizations': active_orgs}) return self.get_response({'form': form}) enabled_orgs = form.cleaned_data['organizations'] disabled_orgs = list( set(o.id for o in organizations) - set(enabled_orgs)) # Remove organization and project Jira integrations not in the set of # enabled organizations OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=disabled_orgs, ).delete() ProjectIntegration.objects.filter( integration__provider='jira', integration=integration, integration__organizations__in=disabled_orgs, ).delete() # Ensure all enabled integrations. for org_id in enabled_orgs: integration.add_organization(org_id) return self.get_response({'form': form, 'completed': True})
def handle(self, request, organization, member_id): try: member = OrganizationMember.objects.get( Q(user__is_active=True) | Q(user__isnull=True), id=member_id, ) except OrganizationMember.DoesNotExist: return self.redirect(reverse('sentry')) if request.POST.get('op') == 'reinvite' and member.is_pending: return self.resend_invite(request, organization, member) can_admin = request.access.has_scope('member:delete') if can_admin and not request.is_superuser(): acting_member = OrganizationMember.objects.get( user=request.user, organization=organization, ) can_admin = acting_member.can_manage_member(member) if member.user == request.user or not can_admin: return self.view_member(request, organization, member) form = self.get_form(request, member) if form.is_valid(): member = form.save(request.user, organization, request.META['REMOTE_ADDR']) messages.add_message(request, messages.SUCCESS, _('Your changes were saved.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, member.id]) return self.redirect(redirect) context = { 'member': member, 'form': form, 'role_list': roles.get_all(), } return self.respond('sentry/organization-member-settings.html', context)
def view_member(self, request, organization, member): context = { 'member': member, 'enabled_teams': set(member.teams.all()), # 'all_teams': Team.objects.filter( # organization=organization, # ), # 当前登陆人具有权限的小组 update by hzwangzhiwei @20160830 'all_teams': Team.objects.get_for_user(organization=organization, user=request.user), 'role_list': roles.get_all(), } return self.respond('sentry/organization-member-details.html', context)
def handle(self, request): try: integration = get_integration_from_request(request) except AtlassianConnectValidationError: return self.get_response({'error_message': 'Unable to verify installation.'}) organizations = request.user.get_orgs().filter( id__in=OrganizationMember.objects.filter( role__in=[r.id for r in roles.get_all() if r.is_global], ), ) form = JiraConfigForm(organizations, request.POST) if request.method == 'GET' or not form.is_valid(): active_orgs = OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=organizations ).values_list('organization_id', flat=True) form = JiraConfigForm(organizations, initial={'organizations': active_orgs}) return self.get_response({'form': form}) enabled_orgs = form.cleaned_data['organizations'] disabled_orgs = list(set(o.id for o in organizations) - set(enabled_orgs)) # Remove organization and project Jira integrations not in the set of # enabled organizations OrganizationIntegration.objects.filter( integration__provider='jira', integration=integration, organization__in=disabled_orgs, ).delete() ProjectIntegration.objects.filter( integration__provider='jira', integration=integration, integration__organizations__in=disabled_orgs, ).delete() # Ensure all enabled integrations. for org_id in enabled_orgs: integration.add_organization(org_id) return self.get_response({'form': form, 'completed': True})
def handle(self, request, organization, member_id): try: member = OrganizationMember.objects.get( Q(user__is_active=True) | Q(user__isnull=True), id=member_id, ) except OrganizationMember.DoesNotExist: return self.redirect(reverse('sentry')) if request.POST.get('op') == 'reinvite' and member.is_pending: return self.resend_invite(request, organization, member) can_admin = request.access.has_scope('member:delete') if can_admin and not is_active_superuser(request): acting_member = OrganizationMember.objects.get( user=request.user, organization=organization, ) can_admin = acting_member.can_manage_member(member) if member.user == request.user or not can_admin: return self.view_member(request, organization, member) form = self.get_form(request, member) if form.is_valid(): member = form.save(request.user, organization, request.META['REMOTE_ADDR']) messages.add_message(request, messages.SUCCESS, _('Your changes were saved.')) redirect = reverse('sentry-organization-member-settings', args=[organization.slug, member.id]) return self.redirect(redirect) context = { 'member': member, 'form': form, 'role_list': roles.get_all(), } return self.respond('sentry/organization-member-settings.html', context)
def handle(self, request, organization): can_admin, allowed_roles = self.get_allowed_roles( request, organization) all_teams = Team.objects.filter(organization=organization, status=TeamStatus.VISIBLE) form = self.get_form(request, organization, all_teams, allowed_roles) if form.is_valid(): om, created = form.save(request.user, organization, request.META['REMOTE_ADDR']) user_display = form.cleaned_data.get('email', None) if not user_display: user_display = form.cleaned_data['user'] if created: messages.add_message( request, messages.SUCCESS, _('The organization member %s was added.') % user_display) member_invited.send(member=om, user=request.user, sender=self) else: messages.add_message( request, messages.INFO, _('The organization member %s already exists.') % user_display) redirect = reverse('sentry-organization-members', args=[organization.slug]) return HttpResponseRedirect(redirect) context = { 'form': form, 'is_invite': settings.SENTRY_ENABLE_INVITES, 'role_list': [(r, r in allowed_roles) for r in roles.get_all()], 'all_teams': list(all_teams), } return self.respond('sentry/create-organization-member.html', context)
def get(self, request, organization, member_id): """Currently only returns allowed invite roles for member invite""" try: member = self._get_member(request, organization, member_id) except OrganizationMember.DoesNotExist: raise ResourceDoesNotExist _, allowed_roles = get_allowed_roles(request, organization, member) allowed_roles = [{'role': serialize(r, serializer=RoleSerializer()), 'allowed': r in allowed_roles} for r in roles.get_all()] context = serialize( member, ) context['allowed_roles'] = allowed_roles return Response(context)
def get(self, request, organization, member_id): """Currently only returns allowed invite roles for member invite""" try: member = self._get_member(request, organization, member_id) except OrganizationMember.DoesNotExist: raise ResourceDoesNotExist _, allowed_roles = get_allowed_roles(request, organization, member) allowed_roles = [{ 'role': serialize(r, serializer=RoleSerializer()), 'allowed': r in allowed_roles } for r in roles.get_all()] context = serialize(member, ) context['allowed_roles'] = allowed_roles return Response(context)
def handle(self, request, organization): can_admin, allowed_roles = self.get_allowed_roles(request, organization) all_teams = Team.objects.filter( organization=organization, status=TeamStatus.VISIBLE ) form = self.get_form(request, organization, all_teams, allowed_roles) if form.is_valid(): om, created = form.save(request.user, organization, request.META['REMOTE_ADDR']) user_display = form.cleaned_data.get('email', None) if not user_display: user_display = form.cleaned_data['user'] if created: messages.add_message(request, messages.SUCCESS, _('The organization member %s was added.') % user_display) member_invited.send(member=om, user=request.user, sender=self) else: messages.add_message(request, messages.INFO, _('The organization member %s already exists.') % user_display) redirect = reverse('sentry-organization-members', args=[organization.slug]) return HttpResponseRedirect(redirect) context = { 'form': form, 'is_invite': settings.SENTRY_ENABLE_INVITES, 'role_list': [ (r, r in allowed_roles) for r in roles.get_all() ], 'all_teams': list(all_teams), } return self.respond('sentry/create-organization-member.html', context)
def serialize(self, obj, attrs, user, access): from sentry import experiments from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = self._team_list(obj, access) project_list = self._project_list(obj, access) onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj, ).select_related('user')) experiment_assignments = experiments.all(org=obj, actor=user) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context['experiments'] = experiment_assignments context['quota'] = { 'maxRate': max_rate[0], 'maxRateInterval': max_rate[1], 'accountLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:account-rate-limit', default=ACCOUNT_RATE_LIMIT_DEFAULT, )), 'projectLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:project-rate-limit', default=PROJECT_RATE_LIMIT_DEFAULT, )), } context.update({ 'isDefault': obj.is_default, 'defaultRole': obj.default_role, 'availableRoles': [{ 'id': r.id, 'name': r.name, } for r in roles.get_all()], 'openMembership': bool(obj.flags.allow_joinleave), 'require2FA': bool(obj.flags.require_2fa), 'allowSharedIssues': not obj.flags.disable_shared_issues, 'enhancedPrivacy': bool(obj.flags.enhanced_privacy), 'dataScrubber': bool( obj.get_option('sentry:require_scrub_data', REQUIRE_SCRUB_DATA_DEFAULT)), 'dataScrubberDefaults': bool( obj.get_option('sentry:require_scrub_defaults', REQUIRE_SCRUB_DEFAULTS_DEFAULT)), 'sensitiveFields': obj.get_option('sentry:sensitive_fields', SENSITIVE_FIELDS_DEFAULT) or [], 'safeFields': obj.get_option('sentry:safe_fields', SAFE_FIELDS_DEFAULT) or [], 'storeCrashReports': bool( obj.get_option('sentry:store_crash_reports', STORE_CRASH_REPORTS_DEFAULT)), 'scrubIPAddresses': bool( obj.get_option('sentry:require_scrub_ip_address', REQUIRE_SCRUB_IP_ADDRESS_DEFAULT)), 'scrapeJavaScript': bool( obj.get_option('sentry:scrape_javascript', SCRAPE_JAVASCRIPT_DEFAULT)), 'trustedRelays': obj.get_option('sentry:trusted-relays', TRUSTED_RELAYS_DEFAULT) or [], }) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) context['access'] = access.scopes context[ 'pendingAccessRequests'] = OrganizationAccessRequest.objects.filter( team__organization=obj, ).count() context['onboardingTasks'] = serialize(onboarding_tasks, user, OnboardingTasksSerializer()) return context
def put(self, request, organization, member_id): """ Update an invite request to Organization ```````````````````````````````````````` Update and/or approve an invite request to an organization. :pparam string organization_slug: the slug of the organization the member will belong to :param string member_id: the member ID :param boolean approve: allows the member to be invited :param string role: the suggested role of the new member :param array teams: the suggested slugs of the teams the member should belong to. :auth: required """ try: member = self._get_member(organization, member_id) except OrganizationMember.DoesNotExist: raise ResourceDoesNotExist serializer = OrganizationMemberSerializer( data=request.data, context={ "organization": organization, "allowed_roles": roles.get_all() }, partial=True, ) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) result = serializer.validated_data if result.get("role"): member.update(role=result["role"]) if "teams" in result: save_team_assignments(member, result["teams"]) if "approve" in request.data: _, allowed_roles = get_allowed_roles(request, organization) serializer = ApproveInviteRequestSerializer( data=request.data, context={ "request": request, "organization": organization, "member": member, "allowed_roles": allowed_roles, }, ) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) result = serializer.validated_data if result.get("approve") and not member.invite_approved: member.approve_invite() member.save() if settings.SENTRY_ENABLE_INVITES: member.send_invite_email() member_invited.send_robust( member=member, user=request.user, sender=self, referrer=request.data.get("referrer"), ) self.create_audit_entry( request=request, organization_id=organization.id, target_object=member.id, data=member.get_audit_log_data(), event=AuditLogEntryEvent.MEMBER_INVITE if settings.SENTRY_ENABLE_INVITES else AuditLogEntryEvent.MEMBER_ADD, ) return Response( serialize(member, serializer=OrganizationMemberWithTeamsSerializer()), status=status.HTTP_200_OK, )
def serialize(self, obj, attrs, user, access): from sentry import experiments onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj).select_related("user")) experiment_assignments = experiments.all(org=obj, actor=user) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context["experiments"] = experiment_assignments context["quota"] = { "maxRate": max_rate[0], "maxRateInterval": max_rate[1], "accountLimit": int( OrganizationOption.objects.get_value( organization=obj, key="sentry:account-rate-limit", default=ACCOUNT_RATE_LIMIT_DEFAULT, )), "projectLimit": int( OrganizationOption.objects.get_value( organization=obj, key="sentry:project-rate-limit", default=PROJECT_RATE_LIMIT_DEFAULT, )), } context.update({ "isDefault": obj.is_default, "defaultRole": obj.default_role, "availableRoles": [{ "id": r.id, "name": r.name } for r in roles.get_all()], "openMembership": bool(obj.flags.allow_joinleave), "require2FA": bool(obj.flags.require_2fa), "allowSharedIssues": not obj.flags.disable_shared_issues, "enhancedPrivacy": bool(obj.flags.enhanced_privacy), "dataScrubber": bool( obj.get_option("sentry:require_scrub_data", REQUIRE_SCRUB_DATA_DEFAULT)), "dataScrubberDefaults": bool( obj.get_option("sentry:require_scrub_defaults", REQUIRE_SCRUB_DEFAULTS_DEFAULT)), "sensitiveFields": obj.get_option("sentry:sensitive_fields", SENSITIVE_FIELDS_DEFAULT) or [], "safeFields": obj.get_option("sentry:safe_fields", SAFE_FIELDS_DEFAULT) or [], "storeCrashReports": convert_crashreport_count( obj.get_option("sentry:store_crash_reports")), "attachmentsRole": six.text_type( obj.get_option("sentry:attachments_role", ATTACHMENTS_ROLE_DEFAULT)), "debugFilesRole": six.text_type( obj.get_option("sentry:debug_files_role", DEBUG_FILES_ROLE_DEFAULT)), "eventsMemberAdmin": bool( obj.get_option("sentry:events_member_admin", EVENTS_MEMBER_ADMIN_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)), "allowJoinRequests": bool(obj.get_option("sentry:join_requests", JOIN_REQUESTS_DEFAULT)), "relayPiiConfig": six.text_type(obj.get_option("sentry:relay_pii_config") or u"") or None, "apdexThreshold": int( obj.get_option("sentry:apdex_threshold", APDEX_THRESHOLD_DEFAULT)), }) trusted_relays_raw = obj.get_option("sentry:trusted-relays") or [] # serialize trusted relays info into their external form context["trustedRelays"] = [ TrustedRelaySerializer(raw).data for raw in trusted_relays_raw ] context["access"] = access.scopes if access.role is not None: context["role"] = access.role context[ "pendingAccessRequests"] = OrganizationAccessRequest.objects.filter( team__organization=obj).count() context["onboardingTasks"] = serialize(onboarding_tasks, user, OnboardingTasksSerializer()) return context
def serialize(self, obj, attrs, user): from sentry import features from sentry.app import env from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = list(Team.objects.filter( organization=obj, status=TeamStatus.VISIBLE, )) for team in team_list: team._organization_cache = obj project_list = list(Project.objects.filter( organization=obj, status=ProjectStatus.VISIBLE, )) for project in project_list: project._organization_cache = obj onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj, ).select_related('user') ) feature_list = [] if features.has('organizations:sso', obj, actor=user): feature_list.append('sso') if features.has('organizations:onboarding', obj, actor=user) and \ not OrganizationOption.objects.filter(organization=obj).exists(): feature_list.append('onboarding') if features.has('organizations:api-keys', obj, actor=user) or \ ApiKey.objects.filter(organization=obj).exists(): feature_list.append('api-keys') if features.has('organizations:group-unmerge', obj, actor=user): feature_list.append('group-unmerge') if features.has('organizations:github-apps', obj, actor=user): feature_list.append('github-apps') if features.has('organizations:integrations-v3', obj, actor=user): feature_list.append('integrations-v3') if features.has('organizations:new-settings', obj, actor=user): feature_list.append('new-settings') if features.has('organizations:require-2fa', obj, actor=user): feature_list.append('require-2fa') if features.has('organizations:environments', obj, actor=user): feature_list.append('environments') if features.has('organizations:repos', obj, actor=user): feature_list.append('repos') if features.has('organizations:internal-catchall', obj, actor=user): feature_list.append('internal-catchall') if features.has('organizations:suggested-commits', obj, actor=user): feature_list.append('suggested-commits') if features.has('organizations:new-teams', obj, actor=user): feature_list.append('new-teams') if features.has('organizations:unreleased-changes', obj, actor=user): feature_list.append('unreleased-changes') if features.has('organizations:relay', obj, actor=user): feature_list.append('relay') if features.has('organizations:health', obj, actor=user): feature_list.append('health') if getattr(obj.flags, 'allow_joinleave'): feature_list.append('open-membership') if not getattr(obj.flags, 'disable_shared_issues'): feature_list.append('shared-issues') if getattr(obj.flags, 'require_2fa'): feature_list.append('require-2fa') context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context['quota'] = { 'maxRate': max_rate[0], 'maxRateInterval': max_rate[1], 'accountLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:account-rate-limit', default=0, ) ), 'projectLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:project-rate-limit', default=100, ) ), } context.update({ 'isDefault': obj.is_default, 'defaultRole': obj.default_role, 'availableRoles': [{ 'id': r.id, 'name': r.name, } for r in roles.get_all()], 'openMembership': bool(obj.flags.allow_joinleave), 'require2FA': bool(obj.flags.require_2fa), 'allowSharedIssues': not obj.flags.disable_shared_issues, 'enhancedPrivacy': bool(obj.flags.enhanced_privacy), 'dataScrubber': bool(obj.get_option('sentry:require_scrub_data', False)), 'dataScrubberDefaults': bool(obj.get_option('sentry:require_scrub_defaults', False)), 'sensitiveFields': obj.get_option('sentry:sensitive_fields', None) or [], 'safeFields': obj.get_option('sentry:safe_fields', None) or [], 'scrubIPAddresses': bool(obj.get_option('sentry:require_scrub_ip_address', False)), }) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) if env.request: context['access'] = access.from_request(env.request, obj).scopes else: context['access'] = access.from_user(user, obj).scopes context['features'] = feature_list context['pendingAccessRequests'] = OrganizationAccessRequest.objects.filter( team__organization=obj, ).count() context['onboardingTasks'] = serialize(onboarding_tasks, user, OnboardingTasksSerializer()) return context
def serialize(self, obj, attrs, user, access): from sentry import experiments from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = self._team_list(obj, access) project_list = self._project_list(obj, access) onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj, ).select_related('user') ) experiment_assignments = experiments.all(org=obj, actor=user) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context['experiments'] = experiment_assignments context['quota'] = { 'maxRate': max_rate[0], 'maxRateInterval': max_rate[1], 'accountLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:account-rate-limit', default=ACCOUNT_RATE_LIMIT_DEFAULT, ) ), 'projectLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:project-rate-limit', default=PROJECT_RATE_LIMIT_DEFAULT, ) ), } context.update({ 'isDefault': obj.is_default, 'defaultRole': obj.default_role, 'availableRoles': [{ 'id': r.id, 'name': r.name, } for r in roles.get_all()], 'openMembership': bool(obj.flags.allow_joinleave), 'require2FA': bool(obj.flags.require_2fa), 'allowSharedIssues': not obj.flags.disable_shared_issues, 'enhancedPrivacy': bool(obj.flags.enhanced_privacy), 'dataScrubber': bool(obj.get_option('sentry:require_scrub_data', REQUIRE_SCRUB_DATA_DEFAULT)), 'dataScrubberDefaults': bool(obj.get_option('sentry:require_scrub_defaults', REQUIRE_SCRUB_DEFAULTS_DEFAULT)), 'sensitiveFields': obj.get_option('sentry:sensitive_fields', SENSITIVE_FIELDS_DEFAULT) or [], 'safeFields': obj.get_option('sentry:safe_fields', SAFE_FIELDS_DEFAULT) or [], 'storeCrashReports': bool(obj.get_option('sentry:store_crash_reports', STORE_CRASH_REPORTS_DEFAULT)), 'scrubIPAddresses': bool(obj.get_option('sentry:require_scrub_ip_address', REQUIRE_SCRUB_IP_ADDRESS_DEFAULT)), 'scrapeJavaScript': bool(obj.get_option('sentry:scrape_javascript', SCRAPE_JAVASCRIPT_DEFAULT)), 'trustedRelays': obj.get_option('sentry:trusted-relays', TRUSTED_RELAYS_DEFAULT) or [], }) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) context['access'] = access.scopes context['pendingAccessRequests'] = OrganizationAccessRequest.objects.filter( team__organization=obj, ).count() context['onboardingTasks'] = serialize(onboarding_tasks, user, OnboardingTasksSerializer()) return context
def put(self, request: Request, organization, member_id) -> Response: """ Update an invite request to Organization ```````````````````````````````````````` Update and/or approve an invite request to an organization. :pparam string organization_slug: the slug of the organization the member will belong to :param string member_id: the member ID :param boolean approve: allows the member to be invited :param string role: the suggested role of the new member :param array teams: the suggested slugs of the teams the member should belong to. :auth: required """ try: member = self._get_member(organization, member_id) except OrganizationMember.DoesNotExist: raise ResourceDoesNotExist serializer = OrganizationMemberSerializer( data=request.data, context={ "organization": organization, "allowed_roles": roles.get_all() }, partial=True, ) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) result = serializer.validated_data if result.get("role"): member.update(role=result["role"]) if "teams" in result: save_team_assignments(member, result["teams"]) if "approve" in request.data: _, allowed_roles = get_allowed_roles(request, organization) serializer = ApproveInviteRequestSerializer( data=request.data, context={ "request": request, "organization": organization, "member": member, "allowed_roles": allowed_roles, }, ) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) result = serializer.validated_data if result.get("approve") and not member.invite_approved: api_key = get_api_key_for_audit_log(request) member.approve_member_invitation( request.user, api_key, request.META["REMOTE_ADDR"], request.data.get("referrer"), ) return Response( serialize(member, serializer=OrganizationMemberWithTeamsSerializer()), status=status.HTTP_200_OK, )
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
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
def serialize(self, obj, attrs, user, access): from sentry import experiments onboarding_tasks = list( OrganizationOnboardingTask.objects.filter(organization=obj).select_related("user") ) experiment_assignments = experiments.all(org=obj, actor=user) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context["experiments"] = experiment_assignments context["quota"] = { "maxRate": max_rate[0], "maxRateInterval": max_rate[1], "accountLimit": int( OrganizationOption.objects.get_value( organization=obj, key="sentry:account-rate-limit", default=ACCOUNT_RATE_LIMIT_DEFAULT, ) ), "projectLimit": int( OrganizationOption.objects.get_value( organization=obj, key="sentry:project-rate-limit", default=PROJECT_RATE_LIMIT_DEFAULT, ) ), } context.update( { "isDefault": obj.is_default, "defaultRole": obj.default_role, "availableRoles": [{"id": r.id, "name": r.name} for r in roles.get_all()], "openMembership": bool(obj.flags.allow_joinleave), "require2FA": bool(obj.flags.require_2fa), "allowSharedIssues": not obj.flags.disable_shared_issues, "enhancedPrivacy": bool(obj.flags.enhanced_privacy), "dataScrubber": bool( obj.get_option("sentry:require_scrub_data", REQUIRE_SCRUB_DATA_DEFAULT) ), "dataScrubberDefaults": bool( obj.get_option("sentry:require_scrub_defaults", REQUIRE_SCRUB_DEFAULTS_DEFAULT) ), "sensitiveFields": obj.get_option( "sentry:sensitive_fields", SENSITIVE_FIELDS_DEFAULT ) or [], "safeFields": obj.get_option("sentry:safe_fields", SAFE_FIELDS_DEFAULT) or [], "storeCrashReports": bool( obj.get_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_DEFAULT) ), "attachmentsRole": six.text_type( obj.get_option("sentry:attachments_role", ATTACHMENTS_ROLE_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["access"] = access.scopes context["pendingAccessRequests"] = OrganizationAccessRequest.objects.filter( team__organization=obj ).count() context["onboardingTasks"] = serialize(onboarding_tasks, user, OnboardingTasksSerializer()) return context
def serialize(self, obj, attrs, user): from sentry import features, experiments from sentry.features.base import OrganizationFeature from sentry.app import env from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = sorted(Team.objects.filter( organization=obj, status=TeamStatus.VISIBLE, ), key=lambda x: x.slug) for team in team_list: team._organization_cache = obj project_list = sorted(Project.objects.filter( organization=obj, status=ProjectStatus.VISIBLE, ), key=lambda x: x.slug) for project in project_list: project._organization_cache = obj onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj, ).select_related('user') ) # Retrieve all registered organization features org_features = features.all(feature_type=OrganizationFeature).keys() feature_list = set() for feature_name in org_features: if not feature_name.startswith('organizations:'): continue if features.has(feature_name, obj, actor=user): # Remove the organization scope prefix feature_list.add(feature_name[len('organizations:'):]) # Do not include the onboarding feature if OrganizationOptions exist if 'onboarding' in feature_list and \ OrganizationOption.objects.filter(organization=obj).exists(): feature_list.remove('onboarding') # Include api-keys feature if they previously had any api-keys if 'api-keys' not in feature_list and ApiKey.objects.filter(organization=obj).exists(): feature_list.add('api-keys') # Organization flag features (not provided through the features module) if OrganizationOption.objects.filter( organization=obj, key__in=LEGACY_RATE_LIMIT_OPTIONS).exists(): feature_list.add('legacy-rate-limits') if getattr(obj.flags, 'allow_joinleave'): # noqa: B009 feature_list.add('open-membership') if not getattr(obj.flags, 'disable_shared_issues'): # noqa: B009 feature_list.add('shared-issues') if getattr(obj.flags, 'require_2fa'): # noqa: B009 feature_list.add('require-2fa') experiment_assignments = experiments.all(org=obj, actor=user) context = super(DetailedOrganizationSerializer, self).serialize(obj, attrs, user) max_rate = quotas.get_maximum_quota(obj) context['experiments'] = experiment_assignments context['quota'] = { 'maxRate': max_rate[0], 'maxRateInterval': max_rate[1], 'accountLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:account-rate-limit', default=ACCOUNT_RATE_LIMIT_DEFAULT, ) ), 'projectLimit': int( OrganizationOption.objects.get_value( organization=obj, key='sentry:project-rate-limit', default=PROJECT_RATE_LIMIT_DEFAULT, ) ), } context.update({ 'isDefault': obj.is_default, 'defaultRole': obj.default_role, 'availableRoles': [{ 'id': r.id, 'name': r.name, } for r in roles.get_all()], 'openMembership': bool(obj.flags.allow_joinleave), 'require2FA': bool(obj.flags.require_2fa), 'allowSharedIssues': not obj.flags.disable_shared_issues, 'enhancedPrivacy': bool(obj.flags.enhanced_privacy), 'dataScrubber': bool(obj.get_option('sentry:require_scrub_data', REQUIRE_SCRUB_DATA_DEFAULT)), 'dataScrubberDefaults': bool(obj.get_option('sentry:require_scrub_defaults', REQUIRE_SCRUB_DEFAULTS_DEFAULT)), 'sensitiveFields': obj.get_option('sentry:sensitive_fields', SENSITIVE_FIELDS_DEFAULT) or [], 'safeFields': obj.get_option('sentry:safe_fields', SAFE_FIELDS_DEFAULT) or [], 'storeCrashReports': bool(obj.get_option('sentry:store_crash_reports', STORE_CRASH_REPORTS_DEFAULT)), 'scrubIPAddresses': bool(obj.get_option('sentry:require_scrub_ip_address', REQUIRE_SCRUB_IP_ADDRESS_DEFAULT)), 'scrapeJavaScript': bool(obj.get_option('sentry:scrape_javascript', SCRAPE_JAVASCRIPT_DEFAULT)), 'trustedRelays': obj.get_option('sentry:trusted-relays', TRUSTED_RELAYS_DEFAULT) or [], }) context['teams'] = serialize(team_list, user, TeamSerializer()) context['projects'] = serialize(project_list, user, ProjectSummarySerializer()) if env.request: context['access'] = access.from_request(env.request, obj).scopes else: context['access'] = access.from_user(user, obj).scopes context['features'] = feature_list context['pendingAccessRequests'] = OrganizationAccessRequest.objects.filter( team__organization=obj, ).count() context['onboardingTasks'] = serialize(onboarding_tasks, user, OnboardingTasksSerializer()) return context
def serialize(self, obj, attrs, user): from sentry import features, experiments from sentry.app import env from sentry.api.serializers.models.project import ProjectSummarySerializer from sentry.api.serializers.models.team import TeamSerializer team_list = sorted(Team.objects.filter( organization=obj, status=TeamStatus.VISIBLE, ), key=lambda x: x.slug) for team in team_list: team._organization_cache = obj project_list = sorted(Project.objects.filter( organization=obj, status=ProjectStatus.VISIBLE, ), key=lambda x: x.slug) for project in project_list: project._organization_cache = obj onboarding_tasks = list( OrganizationOnboardingTask.objects.filter( organization=obj, ).select_related('user') ) feature_list = [] if features.has('organizations:sso', obj, actor=user): feature_list.append('sso') if features.has('organizations:onboarding', obj, actor=user) and \ not OrganizationOption.objects.filter(organization=obj).exists(): feature_list.append('onboarding') if features.has('organizations:api-keys', obj, actor=user) or \ ApiKey.objects.filter(organization=obj).exists(): feature_list.append('api-keys') if features.has('organizations:group-unmerge', obj, actor=user): feature_list.append('group-unmerge') if features.has('organizations:github-apps', obj, actor=user): feature_list.append('github-apps') if features.has('organizations:require-2fa', obj, actor=user): feature_list.append('require-2fa') if features.has('organizations:repos', obj, actor=user): feature_list.append('repos') if features.has('organizations:internal-catchall', obj, actor=user): feature_list.append('internal-catchall') if features.has('organizations:new-issue-ui', obj, actor=user): feature_list.append('new-issue-ui') if features.has('organizations:github-enterprise', obj, actor=user): feature_list.append('github-enterprise') if features.has('organizations:bitbucket-integration', obj, actor=user): feature_list.append('bitbucket-integration') if features.has('organizations:jira-integration', obj, actor=user): feature_list.append('jira-integration') if features.has('organizations:vsts-integration', obj, actor=user): feature_list.append('vsts-integration') if features.has('organizations:integrations-issue-basic', obj, actor=user): feature_list.append('integrations-issue-basic') if features.has('organizations:integrations-issue-sync', obj, actor=user): feature_list.append('integrations-issue-sync') if features.has('organizations:suggested-commits', obj, actor=user): feature_list.append('suggested-commits') if features.has('organizations:new-teams', obj, actor=user): feature_list.append('new-teams') if features.has('organizations:unreleased-changes', obj, actor=user): feature_list.append('unreleased-changes') if features.has('organizations:relay', obj, actor=user): feature_list.append('relay') if features.has('organizations:js-loader', obj, actor=user): feature_list.append('js-loader') if features.has('organizations:health', obj, actor=user): feature_list.append('health') if features.has('organizations:discover', obj, actor=user): feature_list.append('discover') if 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