예제 #1
0
    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,
        )
예제 #2
0
    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)