def put( self, request: Request, organization: Organization, member: OrganizationMember, ) -> 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 """ 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 put( self, request: Request, organization: Organization, member: OrganizationMember, ) -> Response: serializer = OrganizationMemberSerializer(data=request.data, partial=True) if not serializer.is_valid(): return Response(status=400) try: auth_provider = AuthProvider.objects.get(organization=organization) auth_provider = auth_provider.get_provider() except AuthProvider.DoesNotExist: auth_provider = None allowed_roles = None result = serializer.validated_data # XXX(dcramer): if/when this expands beyond reinvite we need to check # access level if result.get("reinvite"): if member.is_pending: if ratelimits.for_organization_member_invite( organization=organization, email=member.email, user=request.user, auth=request.auth, ): metrics.incr( "member-invite.attempt", instance="rate_limited", skip_internal=True, sample_rate=1.0, ) return Response({"detail": ERR_RATE_LIMITED}, status=429) if result.get("regenerate"): if request.access.has_scope("member:admin"): member.regenerate_token() member.save() else: return Response({"detail": ERR_INSUFFICIENT_SCOPE}, status=400) if member.token_expired: return Response({"detail": ERR_EXPIRED}, status=400) member.send_invite_email() elif auth_provider and not getattr(member.flags, "sso:linked"): member.send_sso_link_email(request.user, auth_provider) else: # TODO(dcramer): proper error message return Response({"detail": ERR_UNINVITABLE}, status=400) if "teams" in result: # dupe code from member_index # ensure listed teams are real teams teams = list( Team.objects.filter(organization=organization, status=TeamStatus.VISIBLE, slug__in=result["teams"])) if len(set(result["teams"])) != len(teams): return Response({"teams": "Invalid team"}, status=400) with transaction.atomic(): # teams may be empty OrganizationMemberTeam.objects.filter( organizationmember=member).delete() OrganizationMemberTeam.objects.bulk_create([ OrganizationMemberTeam(team=team, organizationmember=member) for team in teams ]) if result.get("role"): _, allowed_roles = get_allowed_roles(request, organization) allowed_role_ids = {r.id for r in allowed_roles} # A user cannot promote others above themselves if result["role"] not in allowed_role_ids: return Response( { "role": "You do not have permission to assign the given role." }, status=403) # A user cannot demote a superior if member.role not in allowed_role_ids: return Response( { "role": "You do not have permission to assign a role to the given user." }, status=403, ) if member.user == request.user and (result["role"] != member.role): return Response( {"detail": "You cannot make changes to your own role."}, status=400) member.update(role=result["role"]) self.create_audit_entry( request=request, organization=organization, target_object=member.id, target_user=member.user, event=AuditLogEntryEvent.MEMBER_EDIT, data=member.get_audit_log_data(), ) context = self._serialize_member(member, request, allowed_roles) return Response(context)