Esempio n. 1
0
    def post(self, request, organization):
        serializer = OrganizationMemberSerializer(
            data={
                "email": request.data.get("userName"),
                "role": roles.get(organization.default_role).id,
            },
            context={
                "organization": organization,
                "allowed_roles": [roles.get(organization.default_role)],
                "allow_existing_invite_request": True,
            },
        )

        if not serializer.is_valid():
            if "email" in serializer.errors and any(
                ("is already a member" in error)
                    for error in serializer.errors["email"]):
                # we include conflict logic in the serializer, check to see if that was
                # our error and if so, return a 409 so the scim IDP knows how to handle
                raise ConflictError(detail=SCIM_409_USER_EXISTS)
            return Response(serializer.errors, status=400)

        result = serializer.validated_data
        with transaction.atomic():
            member = OrganizationMember(
                organization=organization,
                email=result["email"],
                role=result["role"],
                inviter=request.user,
            )

            # TODO: are invite tokens needed for SAML orgs?
            if settings.SENTRY_ENABLE_INVITES:
                member.token = member.generate_token()
            member.save()

        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,
        )

        if settings.SENTRY_ENABLE_INVITES and result.get("sendInvite"):
            member.send_invite_email()
            member_invited.send_robust(
                member=member,
                user=request.user,
                sender=self,
                referrer=request.data.get("referrer"),
            )

        context = serialize(
            member,
            serializer=_scim_member_serializer_with_expansion(organization),
        )
        return Response(context, status=201)
Esempio n. 2
0
def openid_login_callback(request):
    #构造需要检查签名的内容
    OPENID_RESPONSE = dict(request.GET)
    SIGNED_CONTENT = []
    #import json
    #print json.dumps(OPENID_RESPONSE, indent=4)
    for k in OPENID_RESPONSE['openid.signed'][0].split(","):
        response_data = OPENID_RESPONSE["openid.%s" % k]
        SIGNED_CONTENT.append("%s:%s\n" % (k, response_data[0]))
    SIGNED_CONTENT = "".join(SIGNED_CONTENT).encode("UTF-8")
    # 使用associate请求获得的mac_key与SIGNED_CONTENT进行assoc_type hash,
    # 检查是否与OpenID Server返回的一致
    SIGNED_CONTENT_SIG = base64.b64encode(
        hmac.new(base64.b64decode(request.session.get('mac_key', '')),
                 SIGNED_CONTENT, hashlib.sha256).digest())

    if SIGNED_CONTENT_SIG != OPENID_RESPONSE['openid.sig'][0]:
        return '认证失败,请重新登录验证'

    request.session.pop('mac_key', None)
    email = request.GET.get('openid.sreg.email', '')
    fullname = request.GET.get('openid.sreg.fullname', '')
    next_url = request.GET.get('next', '/')

    login_user = User.objects.filter(username__iexact=email)
    if login_user.exists():
        login_user = login_user[0]
        login_user.set_password("sentry_netease_openid_pwd")
        login_user.name = fullname  # update by hzwangzhiwei @20160329
        login_user.save()
    else:
        #不存在数据,则增加数据数用户表
        login_user = User(username=email, name=fullname, email=email)
        login_user.set_password("sentry_netease_openid_pwd")
        login_user.save()  #save to db

    # 如果不存在将这个人加入到组织member表中
    if not OrganizationMember.objects.filter(
            user=login_user, organization=Organization.get_default()).exists():
        # 同时给他们默认的trace收集
        # 将用户到组织中
        orgMember = OrganizationMember(user=login_user,
                                       organization=Organization.get_default())
        orgMember.save()
        orgMember = OrganizationMember.objects.get(
            user=login_user, organization=Organization.get_default())
        # 保存组织者到第一个小组
        orgMemTeam = OrganizationMemberTeam(organizationmember=orgMember,
                                            team=Team.objects.get(id=1))
        orgMemTeam.save()

    # HACK: grab whatever the first backend is and assume it works
    login_user.backend = settings.AUTHENTICATION_BACKENDS[0]

    auth.login(request, login_user)
    # can_register should only allow a single registration
    request.session.pop('can_register', None)
    request.session.pop('needs_captcha', None)
    return HttpResponseRedirect(next_url)
Esempio n. 3
0
    def test_token_expires_at_set_on_save(self):
        organization = self.create_organization()
        member = OrganizationMember(organization=organization, email="*****@*****.**")
        member.token = member.generate_token()
        member.save()

        expires_at = timezone.now() + timedelta(days=INVITE_DAYS_VALID)
        assert member.token_expires_at
        assert member.token_expires_at.date() == expires_at.date()
Esempio n. 4
0
    def test_token_expiration(self):
        organization = self.create_organization()
        member = OrganizationMember(organization=organization, email="*****@*****.**")
        member.token = member.generate_token()
        member.save()

        assert member.is_pending
        assert member.token_expired is False

        member.token_expires_at = timezone.now() - timedelta(minutes=1)
        assert member.token_expired
Esempio n. 5
0
    def test_token_expires_at_set_on_save(self):
        organization = self.create_organization()
        member = OrganizationMember(
            organization=organization,
            email='*****@*****.**')
        member.token = member.generate_token()
        member.save()

        expires_at = timezone.now() + timedelta(days=INVITE_DAYS_VALID)
        assert member.token_expires_at
        assert member.token_expires_at.date() == expires_at.date()
def sentry_update_organization_member(organization, user, role):
    model = sentry_find_organization_member(organization, user)
    existing = model is not None
    if not existing:
        model = OrganizationMember()
        model.user = user
        model.organization = organization
        model.role = role
        model.save()

    return model, existing
Esempio n. 7
0
    def test_set_user(self):
        organization = self.create_organization()
        member = OrganizationMember(organization=organization, email="*****@*****.**")
        member.token = member.generate_token()
        member.save()

        user = self.create_user(email="*****@*****.**")
        member.set_user(user)

        assert member.is_pending is False
        assert member.token_expires_at is None
        assert member.token is None
        assert member.email is None
Esempio n. 8
0
    def test_token_expiration(self):
        organization = self.create_organization()
        member = OrganizationMember(
            organization=organization,
            email='*****@*****.**')
        member.token = member.generate_token()
        member.save()

        assert member.is_pending
        assert member.token_expired is False

        member.token_expires_at = timezone.now() - timedelta(minutes=1)
        assert member.token_expired
Esempio n. 9
0
    def test_set_user(self):
        organization = self.create_organization()
        member = OrganizationMember(
            organization=organization,
            email='*****@*****.**')
        member.token = member.generate_token()
        member.save()

        user = self.create_user(email='*****@*****.**')
        member.set_user(user)

        assert member.is_pending is False
        assert member.token_expires_at is None
        assert member.token is None
        assert member.email is None
    def post(self, request, organization):
        """
        Add a Member to Organization
        ````````````````````````````

        Invite a member to the organization.

        :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 role of the new member
        :param array teams: the slugs of the teams the member should belong to.

        :auth: required
        """
        # TODO: If the member already exists, should this still update the role and team?
        # For now, it doesn't, but simply returns the existing object

        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)

        if not serializer.is_valid():
            return Response(serializer.errors, status=400)

        result = serializer.object

        _, allowed_roles = get_allowed_roles(request, organization)

        # 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'}, 400)

        if not result['role'] in {r.id for r in allowed_roles}:
            return Response(
                {'role': 'You do not have permission to invite that role.'},
                403)

        # This is needed because `email` field is case sensitive, but from a user perspective,
        # Sentry treats email as case-insensitive ([email protected] equals [email protected]).

        existing = OrganizationMember.objects.filter(
            organization=organization,
            user__email__iexact=result['email'],
            user__is_active=True,
        ).exists()

        if existing:
            return Response(
                {'email': 'The user %s is already a member' % result['email']},
                409)

        om = OrganizationMember(organization=organization,
                                email=result['email'],
                                role=result['role'])

        if settings.SENTRY_ENABLE_INVITES:
            om.token = om.generate_token()

        try:
            with transaction.atomic():
                om.save()
        except IntegrityError:
            return Response(
                {'email': 'The user %s is already a member' % result['email']},
                409)

        lock = locks.get(u'org:member:{}'.format(om.id), duration=5)
        with TimedRetryPolicy(10)(lock.acquire):
            self.save_team_assignments(om, teams)

        if settings.SENTRY_ENABLE_INVITES:
            om.send_invite_email()
            member_invited.send_robust(member=om,
                                       user=request.user,
                                       sender=self,
                                       referrer=request.DATA.get('referrer'))

        self.create_audit_entry(
            request=request,
            organization_id=organization.id,
            target_object=om.id,
            data=om.get_audit_log_data(),
            event=AuditLogEntryEvent.MEMBER_INVITE if
            settings.SENTRY_ENABLE_INVITES else AuditLogEntryEvent.MEMBER_ADD,
        )

        return Response(serialize(om), status=201)
    def post(self, request, organization):
        """
        Add a Member to Organization
        ````````````````````````````

        Invite a member to the organization.

        :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 role of the new member
        :param array teams: the 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)

        _, allowed_roles = get_allowed_roles(request, organization)

        serializer = OrganizationMemberSerializer(
            data=request.data,
            context={
                "organization": organization,
                "allowed_roles": allowed_roles,
                "allow_existing_invite_request": True,
            },
        )

        if not serializer.is_valid():
            return Response(serializer.errors, status=400)

        result = serializer.validated_data

        with transaction.atomic():
            # remove any invitation requests for this email before inviting
            OrganizationMember.objects.filter(
                Q(invite_status=InviteStatus.REQUESTED_TO_BE_INVITED.value)
                | Q(invite_status=InviteStatus.REQUESTED_TO_JOIN.value),
                email=result["email"],
                organization=organization,
            ).delete()

            om = OrganizationMember(
                organization=organization,
                email=result["email"],
                role=result["role"],
                inviter=request.user,
            )

            if settings.SENTRY_ENABLE_INVITES:
                om.token = om.generate_token()
            om.save()

        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"])

        if settings.SENTRY_ENABLE_INVITES and result.get("sendInvite"):
            om.send_invite_email()
            member_invited.send_robust(member=om,
                                       user=request.user,
                                       sender=self,
                                       referrer=request.data.get("referrer"))

        self.create_audit_entry(
            request=request,
            organization_id=organization.id,
            target_object=om.id,
            data=om.get_audit_log_data(),
            event=AuditLogEntryEvent.MEMBER_INVITE if
            settings.SENTRY_ENABLE_INVITES else AuditLogEntryEvent.MEMBER_ADD,
        )

        return Response(serialize(om), status=201)
Esempio n. 12
0
 def _set_linked_flag(member: OrganizationMember) -> None:
     if getattr(member.flags,
                "sso:invalid") or not getattr(member.flags, "sso:linked"):
         setattr(member.flags, "sso:invalid", False)
         setattr(member.flags, "sso:linked", True)
         member.save()
    def post(self, request, organization):
        """
        Add a Member to Organization
        ````````````````````````````

        Invite a member to the organization.

        :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 role of the new member
        :param array teams: the slugs of the teams the member should belong to.

        :auth: required
        """
        # TODO: If the member already exists, should this still update the role and team?
        # For now, it doesn't, but simply returns the existing object

        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)

        if not serializer.is_valid():
            return Response(serializer.errors, status=400)

        result = serializer.object

        _, allowed_roles = get_allowed_roles(request, organization)

        # 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'}, 400)

        if not result['role'] in {r.id for r in allowed_roles}:
            return Response({'role': 'You do not have permission to invite that role.'}, 403)

        # This is needed because `email` field is case sensitive, but from a user perspective,
        # Sentry treats email as case-insensitive ([email protected] equals [email protected]).

        existing = OrganizationMember.objects.filter(
            organization=organization,
            user__email__iexact=result['email'],
            user__is_active=True,
        ).exists()

        if existing:
            return Response({'email': 'The user %s is already a member' % result['email']}, 409)

        om = OrganizationMember(
            organization=organization,
            email=result['email'],
            role=result['role'])

        if settings.SENTRY_ENABLE_INVITES:
            om.token = om.generate_token()

        try:
            with transaction.atomic():
                om.save()
        except IntegrityError:
            return Response({'email': 'The user %s is already a member' % result['email']}, 409)

        lock = locks.get(u'org:member:{}'.format(om.id), duration=5)
        with TimedRetryPolicy(10)(lock.acquire):
            self.save_team_assignments(om, teams)

        if settings.SENTRY_ENABLE_INVITES:
            om.send_invite_email()
            member_invited.send_robust(member=om, user=request.user, sender=self,
                                       referrer=request.DATA.get('referrer'))
        self.create_audit_entry(
            request=request,
            organization_id=organization.id,
            target_object=om.id,
            data=om.get_audit_log_data(),
            event=AuditLogEntryEvent.MEMBER_INVITE if settings.SENTRY_ENABLE_INVITES else AuditLogEntryEvent.MEMBER_ADD,
        )

        return Response(serialize(om), status=201)
Esempio n. 14
0
user = User.objects.get(pk=1)

name = 'AgoraVoting'
name2 = 'AuthApi'

if Organization.objects.filter(name=name).count() == 0:
    organization = Organization()
    organization.name = name
    organization.save()

    om = OrganizationMember()
    om.organization = organization
    om.role = 'owner'
    om.user = user
    om.save()

    team = Team()
    team.name = name
    team.organization = organization
    team.save()

    project = Project()
    project.team = team
    project.name = name2
    project.organization = organization
    project.save()
else:
    organization = Organization.objects.filter(name=name).all()[0]
    team = Team.objects.filter(name=name, organization=organization).all()[0]
    project =Project.objects.filter(team=team, name=name2, organization=organization).all()[0]
Esempio n. 15
0
user = User.objects.get(pk=1)

name = 'AgoraVoting'
name2 = 'AuthApi'

if Organization.objects.filter(name=name).count() == 0:
    organization = Organization()
    organization.name = name
    organization.save()

    om = OrganizationMember()
    om.organization = organization
    om.role = 'owner'
    om.user = user
    om.save()

    team = Team()
    team.name = name
    team.organization = organization
    team.save()

    project = Project()
    project.team = team
    project.name = name2
    project.organization = organization
    project.save()
else:
    organization = Organization.objects.filter(name=name).all()[0]
    team = Team.objects.filter(name=name, organization=organization).all()[0]
    project = Project.objects.filter(team=team,
Esempio n. 16
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)