def handle_basic_auth(self, request, organization):
        can_register = features.has('auth:register') or request.session.get('can_register')

        op = request.POST.get('op')
        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(request)
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()

            defaults = {
                'has_global_access': True,
                'type': OrganizationMemberType.MEMBER,
            }

            organization.member_set.create(
                user=user,
                **defaults
            )

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

            login(request, user)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)

            request.session.pop('needs_captcha', None)

            return self.redirect(get_login_redirect(request))

        elif login_form.is_valid():
            login(request, login_form.get_user())

            request.session.pop('needs_captcha', None)

            return self.redirect(get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            request.session['needs_captcha'] = 1
            login_form = self.get_login_form(request)
            login_form.errors.pop('captcha', None)
            if can_register:
                register_form = self.get_register_form(request)
                register_form.errors.pop('captcha', None)

        request.session.set_test_cookie()

        context = {
            'op': op or 'login',
            'login_form': login_form,
            'register_form': register_form,
            'organization': organization,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/organization-login.html', context)
示例#2
0
    def handle(self, request):
        if request.user.is_authenticated():
            return self.redirect(get_login_redirect(request))

        form = AuthenticationForm(request, request.POST or None,
                                  captcha=bool(request.session.get('needs_captcha')))
        if form.is_valid():
            login(request, form.get_user())

            request.session.pop('needs_captcha', None)

            return self.redirect(get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            request.session['needs_captcha'] = 1
            form = AuthenticationForm(request, request.POST or None, captcha=True)
            form.errors.pop('captcha', None)

        request.session.set_test_cookie()

        context = {
            'form': form,
            'next': request.session.get('_next'),
            'CAN_REGISTER': settings.SENTRY_ALLOW_REGISTRATION or request.session.get('can_register'),
            'AUTH_PROVIDERS': get_auth_providers(),
            'SOCIAL_AUTH_CREATE_USERS': settings.SOCIAL_AUTH_CREATE_USERS,
        }
        return self.respond('sentry/login.html', context)
示例#3
0
    def handle_basic_auth(self, request):
        if request.user.is_authenticated():
            return self.redirect(get_login_redirect(request))

        form = AuthenticationForm(
            request, request.POST or None,
            captcha=bool(request.session.get('needs_captcha')),
        )
        if form.is_valid():
            login(request, form.get_user())

            request.session.pop('needs_captcha', None)

            return self.redirect(get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            request.session['needs_captcha'] = 1
            form = AuthenticationForm(request, request.POST or None, captcha=True)
            form.errors.pop('captcha', None)

        request.session.set_test_cookie()

        context = {
            'form': form,
            'CAN_REGISTER': features.has('auth:register') or request.session.get('can_register'),
        }
        return self.respond('sentry/login.html', context)
示例#4
0
    def handle(self, request):
        if request.user.is_authenticated():
            return self.redirect(get_login_redirect(request))

        form = AuthenticationForm(request, request.POST or None, captcha=bool(request.session.get("needs_captcha")))
        if form.is_valid():
            login(request, form.get_user())

            request.session.pop("needs_captcha", None)

            return self.redirect(get_login_redirect(request))

        elif request.POST and not request.session.get("needs_captcha"):
            request.session["needs_captcha"] = 1
            form = AuthenticationForm(request, request.POST or None, captcha=True)
            form.errors.pop("captcha", None)

        request.session.set_test_cookie()

        context = {
            "form": form,
            "next": request.session.get("_next"),
            "CAN_REGISTER": features.has("auth:register") or request.session.get("can_register"),
            "AUTH_PROVIDERS": get_auth_providers(),
            "SOCIAL_AUTH_CREATE_USERS": features.has("social-auth:register"),
        }
        return self.respond("sentry/login.html", context)
示例#5
0
    def handle_basic_auth(self, request):
        can_register = features.has('auth:register') or request.session.get('can_register')

        op = request.POST.get('op')

        # Detect that we are on the register page by url /register/ and
        # then activate the register tab by default.
        if not op and '/register' in request.path_info and can_register:
            op = 'register'

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(request)
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()

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

            auth.login(request, user)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)

            request.session.pop('needs_captcha', None)

            return self.redirect(auth.get_login_redirect(request))

        elif login_form.is_valid():
            auth.login(request, login_form.get_user())

            request.session.pop('needs_captcha', None)

            return self.redirect(auth.get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            auth.log_auth_failure(request, request.POST.get('username'))
            request.session['needs_captcha'] = 1
            login_form = self.get_login_form(request)
            login_form.errors.pop('captcha', None)
            if can_register:
                register_form = self.get_register_form(request)
                register_form.errors.pop('captcha', None)

        request.session.set_test_cookie()

        context = {
            'op': op or 'login',
            'login_form': login_form,
            'register_form': register_form,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/login.html', context)
示例#6
0
    def handle_basic_auth(self, request):
        can_register = features.has('auth:register') or request.session.get('can_register')

        op = request.POST.get('op')

        # Detect that we are on the register page by url /register/ and
        # then activate the register tab by default.
        if not op and '/register' in request.path_info and can_register:
            op = 'register'

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(request, initial={
                'username': request.session.get('invite_email', '')
            })
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

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

            auth.login(request, user)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)
            request.session.pop('invite_email', None)

            return self.redirect(auth.get_login_redirect(request))

        elif login_form.is_valid():
            user = login_form.get_user()

            auth.login(request, user)

            if not user.is_active:
                return self.redirect(reverse('sentry-reactivate-account'))

            return self.redirect(auth.get_login_redirect(request))

        request.session.set_test_cookie()

        context = {
            'op': op or 'login',
            'server_hostname': get_server_hostname(),
            'login_form': login_form,
            'register_form': register_form,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/login.html', context)
示例#7
0
    def handle_basic_auth(self, request):
        can_register = features.has("auth:register") or request.session.get("can_register")

        op = request.POST.get("op")

        # Detect that we are on the register page by url /register/ and
        # then activate the register tab by default.
        if not op and "/register" in request.path_info and can_register:
            op = "register"

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(
                request, initial={"username": request.session.get("invite_email", "")}
            )
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

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

            auth.login(request, user)

            # can_register should only allow a single registration
            request.session.pop("can_register", None)
            request.session.pop("invite_email", None)

            return self.redirect(auth.get_login_redirect(request))

        elif login_form.is_valid():
            user = login_form.get_user()

            auth.login(request, user)

            if not user.is_active:
                return self.redirect(reverse("sentry-reactivate-account"))

            return self.redirect(auth.get_login_redirect(request))

        context = {
            "op": op or "login",
            "server_hostname": get_server_hostname(),
            "login_form": login_form,
            "register_form": register_form,
            "CAN_REGISTER": can_register,
        }
        return self.respond("sentry/login.html", context)
    def handle_basic_auth(self, request, organization):
        can_register = features.has('auth:register') or request.session.get('can_register')

        op = request.POST.get('op')
        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(request)
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

            defaults = {
                'role': 'member',
            }

            organization.member_set.create(
                user=user,
                **defaults
            )

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

            auth.login(request, user, organization_id=organization.id)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)

            return self.redirect(auth.get_login_redirect(request))

        elif login_form.is_valid():
            auth.login(request, login_form.get_user(),
                       organization_id=organization.id)

            return self.redirect(auth.get_login_redirect(request))

        request.session.set_test_cookie()

        context = {
            'op': op or 'login',
            'login_form': login_form,
            'register_form': register_form,
            'organization': organization,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/organization-login.html', context)
示例#9
0
def handle_existing_identity(auth_provider, provider, organization, request,
                             state, auth_identity, identity):
    # TODO(dcramer): this is very similar to attach
    now = timezone.now()
    auth_identity.update(
        data=provider.update_identity(new_data=identity.get("data", {}),
                                      current_data=auth_identity.data),
        last_verified=now,
        last_synced=now,
    )

    try:
        member = OrganizationMember.objects.get(user=auth_identity.user,
                                                organization=organization)
    except OrganizationMember.DoesNotExist:
        # this is likely the case when someone was removed from the org
        # but still has access to rejoin
        member = handle_new_membership(auth_provider, organization, request,
                                       auth_identity)
    else:
        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()

    user = auth_identity.user
    user.backend = settings.AUTHENTICATION_BACKENDS[0]

    if not auth.login(request,
                      user,
                      after_2fa=request.build_absolute_uri(),
                      organization_id=organization.id):
        return HttpResponseRedirect(auth.get_login_redirect(request))

    state.clear()
    metrics.incr(
        "sso.login-success",
        tags={
            "provider": provider.key,
            "organization_id": organization.id,
            "user_id": request.user.id,
        },
        skip_internal=False,
        sample_rate=1.0,
    )

    return HttpResponseRedirect(auth.get_login_redirect(request))
示例#10
0
    def _handle_unknown_identity(self, identity):
        """
        Flow is activated upon a user logging in to where an AuthIdentity is
        not present.

        The flow will attempt to answer the following:

        - Is there an existing user with the same email address? Should they be
          merged?

        - Is there an existing user (via authentication) that shoudl be merged?

        - Should I create a new user based on this identity?
        """
        request = self.request
        op = request.POST.get('op')
        if not request.user.is_authenticated():
            try:
                existing_user = find_users(identity['email'])[0]
            except IndexError:
                existing_user = None
            login_form = self._get_login_form(existing_user)

        if op == 'confirm' and request.user.is_authenticated():
            auth_identity = self._handle_attach_identity(identity)
        elif op == 'newuser':
            auth_identity = self._handle_new_user(identity)
        elif op == 'login' and not request.user.is_authenticated():
            # confirm authentication, login
            op = None
            if login_form.is_valid():
                login(request, login_form.get_user())
                request.session.pop('needs_captcha', None)
            else:
                request.session['needs_captcha'] = 1
        else:
            op = None

        if not op:
            if request.user.is_authenticated():
                return self.respond('sentry/auth-confirm-link.html', {
                    'identity': identity,
                    'existing_user': request.user,
                })

            return self.respond(
                'sentry/auth-confirm-identity.html', {
                    'existing_user': existing_user,
                    'identity': identity,
                    'login_form': login_form,
                })

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        login(self.request, user)

        self.clear_session()

        return HttpResponseRedirect(get_login_redirect(self.request))
示例#11
0
    def _handle_existing_identity(self, auth_identity, identity):
        # TODO(dcramer): this is very similar to attach
        now = timezone.now()
        auth_identity.update(
            data=self.provider.update_identity(
                new_data=identity.get('data', {}),
                current_data=auth_identity.data,
            ),
            last_verified=now,
            last_synced=now,
        )

        try:
            member = OrganizationMember.objects.get(
                user=auth_identity.user,
                organization=self.organization,
            )
        except OrganizationMember.DoesNotExist:
            # this is likely the case when someone was removed from the org
            # but still has access to rejoin
            member = self._handle_new_membership(auth_identity)
        else:
            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()

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        auth.login(self.request, user)

        self.clear_session()

        return HttpResponseRedirect(auth.get_login_redirect(self.request))
示例#12
0
    def post(self, request):
        # need this check for tests since the route will exist even if DEMO_MODE=False
        if not settings.DEMO_MODE:
            raise Http404

        logger.info("post.start")

        # move this import here so we Django doesn't discover the models
        # for demo mode except when Demo mode is actually active
        from sentry.demo.demo_org_manager import assign_demo_org

        # assign the demo org and get the user
        org, user = assign_demo_org()

        logger.info("post.assigned_org", extra={"organization_slug": org.slug})

        auth.login(request, user)

        resp = self.redirect(auth.get_login_redirect(request))
        # set a cookie of whether the user accepteed tracking so we know
        # whether to initialize analytics when accepted_tracking=1
        # 0 means don't show the footer to accept cookies (user already declined)
        # no value means we show the footer to accept cookies (user has neither accepted nor declined)
        accepted_tracking = request.POST.get("accepted_tracking")
        if accepted_tracking in ["0", "1"]:
            resp.set_cookie("accepted_tracking", accepted_tracking)

        return resp
    def handle_basic_auth(self, request, organization):
        form = SimplifiedAuthenticationForm(
            request, request.POST or None,
            captcha=bool(request.session.get('needs_captcha')),
        )

        if form.is_valid():
            login(request, form.get_user())

            request.session.pop('needs_captcha', None)

            return self.redirect(get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            request.session['needs_captcha'] = 1
            form = AuthenticationForm(request, request.POST or None, captcha=True)
            form.errors.pop('captcha', None)

        context = {
            'form': form,
            'CAN_REGISTER': features.has('auth:register') or request.session.get('can_register'),
            'organization': organization,
        }

        return self.respond('sentry/organization-login.html', context)
示例#14
0
    def post(self, request, organization=None, *args, **kwargs):
        """
        Process a login request via username/password. SSO login is handled
        elsewhere.
        """
        login_form = AuthenticationForm(request, request.DATA)

        # Rate limit logins
        is_limited = ratelimiter.is_limited(
            u'auth:login:username:{}'.format(
                md5_text(request.DATA.get('username').lower()).hexdigest()),
            limit=10,
            window=60,  # 10 per minute should be enough for anyone
        )

        if is_limited:
            errors = {'__all__': [login_form.error_messages['rate_limited']]}
            metrics.incr('login.attempt',
                         instance='rate_limited',
                         skip_internal=True,
                         sample_rate=1.0)

            return self.respond_with_error(errors)

        if not login_form.is_valid():
            metrics.incr('login.attempt',
                         instance='failure',
                         skip_internal=True,
                         sample_rate=1.0)
            return self.respond_with_error(login_form.errors)

        user = login_form.get_user()

        auth.login(
            request,
            user,
            organization_id=organization.id if organization else None,
        )
        metrics.incr('login.attempt',
                     instance='success',
                     skip_internal=True,
                     sample_rate=1.0)

        if not user.is_active:
            return Response({
                'nextUri':
                '/auth/reactivate/',
                'user':
                serialize(user, user, DetailedUserSerializer()),
            })

        active_org = self.get_active_organization(request)
        redirect_url = auth.get_org_redirect_url(request, active_org)

        return Response({
            'nextUri':
            auth.get_login_redirect(request, redirect_url),
            'user':
            serialize(user, user, DetailedUserSerializer()),
        })
示例#15
0
文件: helper.py 项目: delkyd/sentry
    def _handle_unknown_identity(self, identity):
        """
        Flow is activated upon a user logging in to where an AuthIdentity is
        not present.

        The flow will attempt to answer the following:

        - Is there an existing user with the same email address? Should they be
          merged?

        - Is there an existing user (via authentication) that shoudl be merged?

        - Should I create a new user based on this identity?
        """
        request = self.request
        op = request.POST.get('op')

        if not request.user.is_authenticated():
            try:
                existing_user = find_users(identity['email'])[0]
            except IndexError:
                existing_user = None
            login_form = self._get_login_form(existing_user)

        if op == 'confirm' and request.user.is_authenticated():
            auth_identity = self._handle_attach_identity(identity)
        elif op == 'newuser':
            auth_identity = self._handle_new_user(identity)
        elif op == 'login' and not request.user.is_authenticated():
            # confirm authentication, login
            op = None
            if login_form.is_valid():
                login(request, login_form.get_user())
                request.session.pop('needs_captcha', None)
            else:
                request.session['needs_captcha'] = 1
        else:
            op = None

        if not op:
            if request.user.is_authenticated():
                return self.respond('sentry/auth-confirm-link.html', {
                    'identity': identity,
                    'existing_user': request.user,
                })

            return self.respond('sentry/auth-confirm-identity.html', {
                'existing_user': existing_user,
                'identity': identity,
                'login_form': login_form,
            })

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        login(self.request, user)

        self.clear_session()

        return HttpResponseRedirect(get_login_redirect(self.request))
示例#16
0
    def post(self, request, organization=None, *args, **kwargs):
        """
        Process a login request via username/password. SSO login is handled
        elsewhere.
        """
        login_form = AuthenticationForm(request, request.data)

        # Rate limit logins
        is_limited = ratelimiter.is_limited(
            "auth:login:username:{}".format(
                md5_text(
                    login_form.clean_username(
                        request.data.get("username"))).hexdigest()),
            limit=10,
            window=60,  # 10 per minute should be enough for anyone
        )

        if is_limited:
            errors = {"__all__": [login_form.error_messages["rate_limited"]]}
            metrics.incr("login.attempt",
                         instance="rate_limited",
                         skip_internal=True,
                         sample_rate=1.0)

            return self.respond_with_error(errors)

        if not login_form.is_valid():
            metrics.incr("login.attempt",
                         instance="failure",
                         skip_internal=True,
                         sample_rate=1.0)
            return self.respond_with_error(login_form.errors)

        user = login_form.get_user()

        auth.login(request,
                   user,
                   organization_id=organization.id if organization else None)
        metrics.incr("login.attempt",
                     instance="success",
                     skip_internal=True,
                     sample_rate=1.0)

        if not user.is_active:
            return Response({
                "nextUri":
                "/auth/reactivate/",
                "user":
                serialize(user, user, DetailedUserSerializer()),
            })

        active_org = self.get_active_organization(request)
        redirect_url = auth.get_org_redirect_url(request, active_org)

        return Response({
            "nextUri":
            auth.get_login_redirect(request, redirect_url),
            "user":
            serialize(user, user, DetailedUserSerializer()),
        })
示例#17
0
文件: helper.py 项目: delkyd/sentry
    def _handle_existing_identity(self, auth_identity, identity):
        # TODO(dcramer): this is very similar to attach
        now = timezone.now()
        auth_identity.update(
            data=identity.get('data', {}),
            last_verified=now,
            last_synced=now,
        )

        try:
            member = OrganizationMember.objects.get(
                user=auth_identity.user,
                organization=self.organization,
            )
        except OrganizationMember.DoesNotExist:
            # this is likely the case when someone was removed from the org
            # but still has access to rejoin
            member = self._handle_new_membership(auth_identity)
        else:
            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()

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        login(self.request, user)

        self.clear_session()

        return HttpResponseRedirect(get_login_redirect(self.request))
示例#18
0
    def handle_basic_auth(self, request, organization):
        can_register = features.has('auth:register') or request.session.get(
            'can_register')

        op = request.POST.get('op')
        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(request)
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

            defaults = {
                'role': 'member',
            }

            organization.member_set.create(user=user, **defaults)

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

            auth.login(request, user)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)

            return self.redirect(auth.get_login_redirect(request))

        elif login_form.is_valid():
            auth.login(request, login_form.get_user())

            return self.redirect(auth.get_login_redirect(request))

        request.session.set_test_cookie()

        context = {
            'op': op or 'login',
            'login_form': login_form,
            'register_form': register_form,
            'organization': organization,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/organization-login.html', context)
示例#19
0
def post_login_redirect(request):
    response = HttpResponseRedirect(auth.get_login_redirect(request))

    # Always remove any pending invite cookies, pending invites will have been
    # accepted during the SSO flow.
    remove_invite_cookie(request, response)

    return response
示例#20
0
 def perform_signin(self, request, user, interface=None):
     auth.login(request, user, passed_2fa=True)
     rv = HttpResponseRedirect(auth.get_login_redirect(request))
     if interface is not None:
         interface.authenticator.mark_used()
         if not interface.is_backup_interface:
             rv.set_cookie(COOKIE_NAME, str(interface.type),
                           max_age=COOKIE_MAX_AGE, path='/')
     return rv
示例#21
0
def handle_existing_identity(auth_provider, provider, organization,
                             request, state, auth_identity, identity):
    # TODO(dcramer): this is very similar to attach
    now = timezone.now()
    auth_identity.update(
        data=provider.update_identity(
            new_data=identity.get('data', {}),
            current_data=auth_identity.data,
        ),
        last_verified=now,
        last_synced=now,
    )

    try:
        member = OrganizationMember.objects.get(
            user=auth_identity.user,
            organization=organization,
        )
    except OrganizationMember.DoesNotExist:
        # this is likely the case when someone was removed from the org
        # but still has access to rejoin
        member = handle_new_membership(auth_provider, organization, request, auth_identity)
    else:
        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()

    user = auth_identity.user
    user.backend = settings.AUTHENTICATION_BACKENDS[0]

    if not auth.login(
        request,
        user,
        after_2fa=request.build_absolute_uri(),
        organization_id=organization.id
    ):
        return HttpResponseRedirect(auth.get_login_redirect(request))

    state.clear()
    metrics.incr('sso.login-success', tags={'provider': provider.key})

    return HttpResponseRedirect(auth.get_login_redirect(request))
示例#22
0
    def dispatch(self, request):
        # need this check for tests since the route will exist even if DEMO_MODE=False
        if not settings.DEMO_MODE:
            raise Http404

        # TODO: add way to ensure we generate unique petnames
        name = generate_random_name()

        slug = slugify(name)

        email = create_fake_email(slug, "demo")
        user = User.objects.create(
            email=email,
            username=email,
            is_managed=True,
            flags=User.flags["demo_mode"],
        )

        org = Organization.objects.create(
            name=name,
            slug=slug,
            flags=Organization.flags["demo_mode"],
        )
        team = org.team_set.create(name=org.name)

        owner = User.objects.get(email=settings.DEMO_ORG_OWNER_EMAIL)
        OrganizationMember.objects.create(organization=org,
                                          user=owner,
                                          role=roles.get_top_dog().id)

        member = OrganizationMember.objects.create(organization=org,
                                                   user=user,
                                                   role="member")
        OrganizationMemberTeam.objects.create(team=team,
                                              organizationmember=member,
                                              is_active=True)

        python_project = Project.objects.create(name="Python",
                                                organization=org,
                                                platform="python")
        python_project.add_team(team)

        reat_project = Project.objects.create(name="React",
                                              organization=org,
                                              platform="javascript-react")
        reat_project.add_team(team)

        populate_python_project(python_project)
        populate_react_project(reat_project)

        # delete all DSNs for the org so people don't send events
        ProjectKey.objects.filter(project__organization=org).delete()

        auth.login(request, user)
        return self.redirect(auth.get_login_redirect(request))
示例#23
0
    def handle(self, request):
        if not request.user.is_authenticated:
            return self.handle_auth_required(request)

        if request.POST.get('op') == 'confirm':
            request.user.update(is_active=True)

            return self.redirect(auth.get_login_redirect(request))

        context = {}
        return self.respond('sentry/reactivate-account.html', context)
示例#24
0
    def handle(self, request):
        if not request.user.is_authenticated():
            return self.handle_auth_required(request)

        if request.POST.get("op") == "confirm":
            request.user.update(is_active=True)

            return self.redirect(auth.get_login_redirect(request))

        context = {}
        return self.respond("sentry/reactivate-account.html", context)
示例#25
0
    def dispatch(self, request, organization_slug):
        provider = get_provider(organization_slug)
        organization = Organization.objects.get(slug=organization_slug)
        saml_config = provider.build_saml_config(organization_slug)

        auth = provider.build_auth(request, saml_config)
        auth.process_response()
        errors = auth.get_errors()
        if errors:
            error_reason = auth.get_last_error_reason()
            raise IdentityNotValid(error_reason)

        attributes = auth.get_attributes()
        nameid = auth.get_nameid()

        email = self.retrieve_email(attributes, nameid, provider.config)

        # Filter users based on the emails provided in the commits
        user_emails = list(
            UserEmail.objects.filter(email__iexact=email,
                                     is_verified=True).order_by('id'))

        if user_emails:
            users = list(
                User.objects.filter(
                    id__in=set((ue.user_id for ue in user_emails)),
                    is_active=True,
                    sentry_orgmember_set__organization_id=organization.id)
                [0:2])
            if users:
                if len(users) == 1:
                    user = users[0]
                    user.backend = settings.AUTHENTICATION_BACKENDS[0]
                    if login(request,
                             user,
                             after_2fa=request.build_absolute_uri(),
                             organization_id=organization.id):
                        request.session['saml'] = {
                            'nameid': nameid,
                            'nameid_format': auth.get_nameid_format(),
                            'session_index': auth.get_session_index()
                        }
                    return HttpResponseRedirect(get_login_redirect(request))
                else:
                    return HttpResponseServerError(
                        "Found several accounts related with %s on this organization"
                        % email)
            else:
                return HttpResponseServerError(
                    "The user %s is not related with this organization" %
                    email)
        else:
            return HttpResponseServerError(
                "An user with a verified mail: %s does not exist" % email)
示例#26
0
    def handle(self, request):
        if request.user.is_authenticated():
            return self.redirect(get_login_redirect(request))

        form = AuthenticationForm(request,
                                  request.POST or None,
                                  captcha=bool(
                                      request.session.get('needs_captcha')))
        if form.is_valid():
            login(request, form.get_user())

            request.session.pop('needs_captcha', None)

            return self.redirect(get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            request.session['needs_captcha'] = 1
            form = AuthenticationForm(request,
                                      request.POST or None,
                                      captcha=True)
            form.errors.pop('captcha', None)

        request.session.set_test_cookie()

        context = {
            'form':
            form,
            'next':
            request.session.get('_next'),
            'CAN_REGISTER':
            features.has('auth:register')
            or request.session.get('can_register'),
            'AUTH_PROVIDERS':
            get_auth_providers(),
            'SOCIAL_AUTH_CREATE_USERS':
            features.has('social-auth:register'),
        }
        return self.respond('sentry/login.html', context)
示例#27
0
    def _finish_login_pipeline(self, identity):
        auth_provider = self.auth_provider

        try:
            auth_identity = AuthIdentity.objects.get(auth_provider=auth_provider, ident=identity["id"])
        except AuthIdentity.DoesNotExist:
            user = User.objects.create(email=identity["email"], first_name=identity.get("name"), is_managed=True)

            AuthIdentity.objects.create(auth_provider=auth_provider, user=user, ident=identity["id"])

            om = OrganizationMember.objects.create(
                organization=self.organization,
                type=auth_provider.default_role,
                has_global_access=auth_provider.default_global_access,
                user=user,
                flags=getattr(OrganizationMember.flags, "sso:linked"),
            )

            default_teams = auth_provider.default_teams.all()
            for team in default_teams:
                om.teams.add(team)

            AuditLogEntry.objects.create(
                organization=self.organization,
                actor=user,
                ip_address=self.request.META["REMOTE_ADDR"],
                target_object=om.id,
                target_user=om.user,
                event=AuditLogEntryEvent.MEMBER_ADD,
                data=om.get_audit_log_data(),
            )
        else:
            now = timezone.now()
            auth_identity.update(data=identity["data"], last_verified=now, last_synced=now)

            om = OrganizationMember.objects.get(user=auth_identity.user, organization=self.organization)
            setattr(om.flags, "sso:invalid", False)
            setattr(om.flags, "sso:linked", True)
            om.save()

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        login(self.request, user)

        return HttpResponseRedirect(get_login_redirect(self.request))
示例#28
0
def get_redirect_url(request, org):
    # determine the redirect based on the scenario
    scenario = request.POST.get("scenario")
    if scenario == "performance":
        return f"/organizations/{org.slug}/performance/"
    if scenario == "releases":
        return f"/organizations/{org.slug}/releases/"
    if scenario == "alerts":
        return f"/organizations/{org.slug}/alerts/"
    if scenario == "discover":
        return f"/organizations/{org.slug}/discover/queries/"
    if scenario == "dashboards":
        return f"/organizations/{org.slug}/dashboards/"
    url = auth.get_login_redirect(request)
    # user is logged in so will be automatically redirected
    # after landing on login page
    url += "?allow_login=1"
    return url
示例#29
0
    def _post_login_redirect(self) -> HttpResponseRedirect:
        url = auth.get_login_redirect(self.request)
        if self.request.POST.get("op") == "newuser":
            # add events that we can handle on the front end
            provider = self.auth_provider.provider if self.auth_provider else None
            params = {
                "frontend_events":
                json.dumps({
                    "event_name": "Sign Up",
                    "event_label": provider
                })
            }
            url = add_params_to_url(url, params)
        response = HttpResponseRedirect(url)

        # Always remove any pending invite cookies, pending invites will have been
        # accepted during the SSO flow.
        remove_invite_cookie(self.request, response)

        return response
示例#30
0
    def post(self, request):
        # need this check for tests since the route will exist even if DEMO_MODE=False
        if not settings.DEMO_MODE:
            raise Http404

        # move this import here so we Django doesn't discover the models
        # for demo mode except when Demo mode is actually active
        from sentry.demo.demo_org_manager import assign_demo_org

        # assign the demo org and get the user
        try:
            _, user = assign_demo_org()
        except NoDemoOrgReady:
            # TODO: handle NoDemoOrgReady error
            raise

        auth.login(request, user)

        resp = self.redirect(auth.get_login_redirect(request))
        # set a cookie of whether the user accepteed tracking so we know
        # whether to initialize analytics when accepted_tracking=1
        resp.set_cookie("accepted_tracking", request.POST.get("accepted_tracking"))

        return resp
示例#31
0
    def handle_basic_auth(self, request):
        can_register = auth.has_user_registration() or request.session.get(
            'can_register')

        op = request.POST.get('op')

        # Detect that we are on the register page by url /register/ and
        # then activate the register tab by default.
        if not op and '/register' in request.path_info and can_register:
            op = 'register'

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(
                request,
                initial={'username': request.session.get('invite_email', '')})
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

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

            auth.login(request, user)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)
            request.session.pop('invite_email', None)

            return self.redirect(auth.get_login_redirect(request))

        elif request.method == 'POST':
            from sentry.app import ratelimiter
            from sentry.utils.hashlib import md5_text

            login_attempt = op == 'login' and request.POST.get(
                'username') and request.POST.get('password')

            if login_attempt and ratelimiter.is_limited(
                    u'auth:login:username:{}'.format(
                        md5_text(
                            request.POST['username'].lower()).hexdigest()),
                    limit=10,
                    window=60,  # 10 per minute should be enough for anyone
            ):
                login_form.errors['__all__'] = [
                    u'You have made too many login attempts. Please try again later.'
                ]
            elif login_form.is_valid():
                user = login_form.get_user()

                auth.login(request, user)

                if not user.is_active:
                    return self.redirect(reverse('sentry-reactivate-account'))

                return self.redirect(auth.get_login_redirect(request))

        context = {
            'op': op or 'login',
            'server_hostname': get_server_hostname(),
            'login_form': login_form,
            'register_form': register_form,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/login.html', context)
示例#32
0
 def test_no_value_uses_default(self):
     result = get_login_redirect(self.make_request())
     assert result == reverse('sentry-login')
示例#33
0
    def _finish_login_pipeline(self, identity):
        """
        The login flow executes both with anonymous and authenticated users.

        Upon completion a few branches exist:

        If the identity is already linked, the user should be logged in
        and redirected immediately.

        Otherwise, the user is presented with a confirmation window. That window
        will show them the new account that will be created, and if they're
        already authenticated an optional button to associate the identity with
        their account.
        """
        auth_provider = self.auth_provider
        request = self.request

        # TODO(dcramer): check for an existing user with the given email address
        # and if one exists, ask them to verify the account for merge

        try:
            auth_identity = AuthIdentity.objects.get(
                auth_provider=auth_provider,
                ident=identity['id'],
            )
        except AuthIdentity.DoesNotExist:
            if request.POST.get(
                    'op') == 'confirm' and request.user.is_authenticated():
                auth_identity = self._handle_attach_identity(identity)
            elif request.POST.get('op') == 'newuser':
                auth_identity = self._handle_new_user(identity)
            else:
                if request.user.is_authenticated():
                    return self.respond('sentry/auth-confirm-link.html', {
                        'identity': identity,
                    })
                return self.respond('sentry/auth-confirm-identity.html', {
                    'identity': identity,
                })
        else:
            # TODO(dcramer): this is very similar to attach
            now = timezone.now()
            auth_identity.update(
                data=identity.get('data', {}),
                last_verified=now,
                last_synced=now,
            )

            try:
                member = OrganizationMember.objects.get(
                    user=auth_identity.user,
                    organization=self.organization,
                )
            except OrganizationMember.DoesNotExist:
                # this is likely the case when someone was removed from the org
                # but still has access to rejoin
                member = self._handle_new_membership(auth_identity)
            else:
                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()

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        login(self.request, user)

        self.clear_session()

        return HttpResponseRedirect(get_login_redirect(self.request))
示例#34
0
文件: helper.py 项目: upwlabs/sentry
    def _handle_unknown_identity(self, identity):
        """
        Flow is activated upon a user logging in to where an AuthIdentity is
        not present.

        The flow will attempt to answer the following:

        - Is there an existing user with the same email address? Should they be
          merged?

        - Is there an existing user (via authentication) that shoudl be merged?

        - Should I create a new user based on this identity?
        """
        request = self.request
        op = request.POST.get('op')

        if not request.user.is_authenticated():
            # TODO(dcramer): its possible they have multiple accounts and at
            # least one is managed (per the check below)
            try:
                existing_user = auth.find_users(identity['email'],
                                                is_active=True)[0]
            except IndexError:
                existing_user = None

            # If they already have an SSO account and the identity provider says
            # the email matches we go ahead and let them merge it. This is the
            # only way to prevent them having duplicate accounts, and because
            # we trust identity providers, its considered safe.
            if existing_user and existing_user.is_managed:
                # we only allow this flow to happen if the existing user has
                # membership, otherwise we short circuit because it might be
                # an attempt to hijack membership of another organization
                has_membership = OrganizationMember.objects.filter(
                    user=existing_user,
                    organization=self.organization,
                ).exists()
                if has_membership:
                    if not auth.login(request,
                                      existing_user,
                                      after_2fa=request.build_absolute_uri(),
                                      organization_id=self.organization.id):
                        return HttpResponseRedirect(
                            auth.get_login_redirect(self.request))
                    # assume they've confirmed they want to attach the identity
                    op = 'confirm'
                else:
                    # force them to create a new account
                    existing_user = None

            login_form = self._get_login_form(existing_user)
        elif request.user.is_managed:
            # per the above, try to auto merge if the user was originally an
            # SSO account but is still logged in
            has_membership = OrganizationMember.objects.filter(
                user=request.user,
                organization=self.organization,
            ).exists()
            if has_membership:
                # assume they've confirmed they want to attach the identity
                op = 'confirm'

        if op == 'confirm' and request.user.is_authenticated():
            auth_identity = self._handle_attach_identity(identity)
        elif op == 'newuser':
            auth_identity = self._handle_new_user(identity)
        elif op == 'login' and not request.user.is_authenticated():
            # confirm authentication, login
            op = None
            if login_form.is_valid():
                # This flow is special.  If we are going through a 2FA
                # flow here (login returns False) we want to instruct the
                # system to return upon completion of the 2fa flow to the
                # current URL and continue with the dialog.
                #
                # If there is no 2fa we don't need to do this and can just
                # go on.
                if not auth.login(request,
                                  login_form.get_user(),
                                  after_2fa=request.build_absolute_uri(),
                                  organization_id=self.organization.id):
                    return HttpResponseRedirect(
                        auth.get_login_redirect(self.request))
            else:
                auth.log_auth_failure(request, request.POST.get('username'))
        else:
            op = None

        if not op:
            if request.user.is_authenticated():
                return self.respond(
                    'sentry/auth-confirm-link.html', {
                        'identity': identity,
                        'existing_user': request.user,
                        'identity_display_name':
                        self._get_display_name(identity),
                        'identity_identifier': self._get_identifier(identity)
                    })

            return self.respond(
                'sentry/auth-confirm-identity.html', {
                    'existing_user': existing_user,
                    'identity': identity,
                    'login_form': login_form,
                    'identity_display_name': self._get_display_name(identity),
                    'identity_identifier': self._get_identifier(identity)
                })

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        # XXX(dcramer): this is repeated from above
        if not auth.login(request,
                          user,
                          after_2fa=request.build_absolute_uri(),
                          organization_id=self.organization.id):
            return HttpResponseRedirect(auth.get_login_redirect(self.request))

        self.clear_session()

        return HttpResponseRedirect(auth.get_login_redirect(self.request))
示例#35
0
def handle_unknown_identity(request, organization, auth_provider, provider, state, identity):
    """
    Flow is activated upon a user logging in to where an AuthIdentity is
    not present.

    XXX(dcramer): this docstring is out of date

    The flow will attempt to answer the following:

    - Is there an existing user with the same email address? Should they be
      merged?

    - Is there an existing user (via authentication) that should be merged?

    - Should I create a new user based on this identity?
    """
    op = request.POST.get('op')
    if not request.user.is_authenticated():
        # TODO(dcramer): its possible they have multiple accounts and at
        # least one is managed (per the check below)
        try:
            acting_user = User.objects.filter(
                id__in=UserEmail.objects.filter(email__iexact=identity['email']).values('user'),
                is_active=True,
            ).first()
        except IndexError:
            acting_user = None
        login_form = AuthenticationForm(
            request,
            request.POST if request.POST.get('op') == 'login' else None,
            initial={
                'username': acting_user.username if acting_user else None,
            },
        )
    else:
        acting_user = request.user

    # If they already have an SSO account and the identity provider says
    # the email matches we go ahead and let them merge it. This is the
    # only way to prevent them having duplicate accounts, and because
    # we trust identity providers, its considered safe.
    # Note: we do not trust things like SAML, so the SSO implementation needs
    # to consider if 'email_verified' can be trusted or not
    if acting_user and identity.get('email_verified'):
        # we only allow this flow to happen if the existing user has
        # membership, otherwise we short circuit because it might be
        # an attempt to hijack membership of another organization
        has_membership = OrganizationMember.objects.filter(
            user=acting_user,
            organization=organization,
        ).exists()
        if has_membership:
            if not auth.login(
                request,
                acting_user,
                after_2fa=request.build_absolute_uri(),
                organization_id=organization.id
            ):
                if acting_user.has_usable_password():
                    return HttpResponseRedirect(auth.get_login_redirect(request))
                else:
                    acting_user = None
            else:
                # assume they've confirmed they want to attach the identity
                op = 'confirm'
        else:
            # force them to create a new account
            acting_user = None
    # without a usable password they cant login, so let's clear the acting_user
    elif acting_user and not acting_user.has_usable_password():
        acting_user = None

    if op == 'confirm' and request.user.is_authenticated():
        auth_identity = handle_attach_identity(
            auth_provider,
            request,
            organization,
            provider,
            identity,
        )
    elif op == 'newuser':
        auth_identity = handle_new_user(auth_provider, organization, request, identity)
    elif op == 'login' and not request.user.is_authenticated():
        # confirm authentication, login
        op = None
        if login_form.is_valid():
            # This flow is special.  If we are going through a 2FA
            # flow here (login returns False) we want to instruct the
            # system to return upon completion of the 2fa flow to the
            # current URL and continue with the dialog.
            #
            # If there is no 2fa we don't need to do this and can just
            # go on.
            if not auth.login(
                request,
                login_form.get_user(),
                after_2fa=request.build_absolute_uri(),
                organization_id=organization.id
            ):
                return HttpResponseRedirect(auth.get_login_redirect(request))
        else:
            auth.log_auth_failure(request, request.POST.get('username'))
    else:
        op = None

    if not op:
        if request.user.is_authenticated():
            return respond(
                'sentry/auth-confirm-link.html',
                organization,
                request,
                {
                    'identity': identity,
                    'existing_user': request.user,
                    'identity_display_name': get_display_name(identity),
                    'identity_identifier': get_identifier(identity)
                },
            )

        return respond(
            'sentry/auth-confirm-identity.html',
            organization,
            request,
            {
                'existing_user': acting_user,
                'identity': identity,
                'login_form': login_form,
                'identity_display_name': get_display_name(identity),
                'identity_identifier': get_identifier(identity)
            },
        )

    user = auth_identity.user
    user.backend = settings.AUTHENTICATION_BACKENDS[0]

    # XXX(dcramer): this is repeated from above
    if not auth.login(
        request,
        user,
        after_2fa=request.build_absolute_uri(),
        organization_id=organization.id
    ):
        return HttpResponseRedirect(auth.get_login_redirect(request))

    state.clear()

    return HttpResponseRedirect(auth.get_login_redirect(request))
示例#36
0
文件: tests.py 项目: Kayle009/sentry
 def test_schema_uses_default(self):
     result = get_login_redirect(self.make_request('http://example.com'))
     assert result == reverse('sentry-login')
示例#37
0
def handle_unknown_identity(request, organization, auth_provider, provider,
                            state, identity):
    """
    Flow is activated upon a user logging in to where an AuthIdentity is
    not present.

    XXX(dcramer): this docstring is out of date

    The flow will attempt to answer the following:

    - Is there an existing user with the same email address? Should they be
      merged?

    - Is there an existing user (via authentication) that should be merged?

    - Should I create a new user based on this identity?
    """
    op = request.POST.get('op')
    if not request.user.is_authenticated():
        # TODO(dcramer): its possible they have multiple accounts and at
        # least one is managed (per the check below)
        try:
            acting_user = User.objects.filter(
                id__in=UserEmail.objects.filter(
                    email__iexact=identity['email']).values('user'),
                is_active=True,
            ).first()
        except IndexError:
            acting_user = None
        login_form = AuthenticationForm(
            request,
            request.POST if request.POST.get('op') == 'login' else None,
            initial={
                'username': acting_user.username if acting_user else None,
            },
        )
    else:
        acting_user = request.user

    # If they already have an SSO account and the identity provider says
    # the email matches we go ahead and let them merge it. This is the
    # only way to prevent them having duplicate accounts, and because
    # we trust identity providers, its considered safe.
    # Note: we do not trust things like SAML, so the SSO implementation needs
    # to consider if 'email_verified' can be trusted or not
    if acting_user and identity.get('email_verified'):
        # we only allow this flow to happen if the existing user has
        # membership, otherwise we short circuit because it might be
        # an attempt to hijack membership of another organization
        has_membership = OrganizationMember.objects.filter(
            user=acting_user,
            organization=organization,
        ).exists()
        if has_membership:
            if not auth.login(request,
                              acting_user,
                              after_2fa=request.build_absolute_uri(),
                              organization_id=organization.id):
                if acting_user.has_usable_password():
                    return HttpResponseRedirect(
                        auth.get_login_redirect(request))
                else:
                    acting_user = None
            else:
                # assume they've confirmed they want to attach the identity
                op = 'confirm'
        else:
            # force them to create a new account
            acting_user = None
    # without a usable password they cant login, so let's clear the acting_user
    elif acting_user and not acting_user.has_usable_password():
        acting_user = None

    if op == 'confirm' and request.user.is_authenticated():
        auth_identity = handle_attach_identity(
            auth_provider,
            request,
            organization,
            provider,
            identity,
        )
    elif op == 'newuser':
        auth_identity = handle_new_user(auth_provider, organization, request,
                                        identity)
    elif op == 'login' and not request.user.is_authenticated():
        # confirm authentication, login
        op = None
        if login_form.is_valid():
            # This flow is special.  If we are going through a 2FA
            # flow here (login returns False) we want to instruct the
            # system to return upon completion of the 2fa flow to the
            # current URL and continue with the dialog.
            #
            # If there is no 2fa we don't need to do this and can just
            # go on.
            if not auth.login(request,
                              login_form.get_user(),
                              after_2fa=request.build_absolute_uri(),
                              organization_id=organization.id):
                return HttpResponseRedirect(auth.get_login_redirect(request))
        else:
            auth.log_auth_failure(request, request.POST.get('username'))
    else:
        op = None

    if not op:
        if request.user.is_authenticated():
            return respond(
                'sentry/auth-confirm-link.html',
                organization,
                request,
                {
                    'identity': identity,
                    'existing_user': request.user,
                    'identity_display_name': get_display_name(identity),
                    'identity_identifier': get_identifier(identity)
                },
            )

        return respond(
            'sentry/auth-confirm-identity.html',
            organization,
            request,
            {
                'existing_user': acting_user,
                'identity': identity,
                'login_form': login_form,
                'identity_display_name': get_display_name(identity),
                'identity_identifier': get_identifier(identity)
            },
        )

    user = auth_identity.user
    user.backend = settings.AUTHENTICATION_BACKENDS[0]

    # XXX(dcramer): this is repeated from above
    if not auth.login(request,
                      user,
                      after_2fa=request.build_absolute_uri(),
                      organization_id=organization.id):
        return HttpResponseRedirect(auth.get_login_redirect(request))

    state.clear()

    return HttpResponseRedirect(auth.get_login_redirect(request))
示例#38
0
 def test_login_uses_default(self):
     result = get_login_redirect(self.make_request(reverse("sentry-login")))
     assert result == reverse("sentry-login")
示例#39
0
def openid_login_index(request):
    # TODO add openid, 在这个地方跳转到openid的位置 by hzwangzhiwei @20160113
    location, mac_key = redirect_url('http://' + request.get_host() + '/',
                                     auth.get_login_redirect(request))
    request.session['mac_key'] = mac_key
    return HttpResponseRedirect(location)  #跳转到openid登陆
示例#40
0
    def _handle_unknown_identity(self, identity):
        """
        Flow is activated upon a user logging in to where an AuthIdentity is
        not present.

        The flow will attempt to answer the following:

        - Is there an existing user with the same email address? Should they be
          merged?

        - Is there an existing user (via authentication) that shoudl be merged?

        - Should I create a new user based on this identity?
        """
        request = self.request
        op = request.POST.get('op')

        if not request.user.is_authenticated():
            # TODO(dcramer): its possible they have multiple accounts and at
            # least one is managed (per the check below)
            try:
                existing_user = auth.find_users(identity['email'], is_active=True)[0]
            except IndexError:
                existing_user = None

            # If they already have an SSO account and the identity provider says
            # the email matches we go ahead and let them merge it. This is the
            # only way to prevent them having duplicate accounts, and because
            # we trust identity providers, its considered safe.
            if existing_user and existing_user.is_managed:
                # we only allow this flow to happen if the existing user has
                # membership, otherwise we short circuit because it might be
                # an attempt to hijack membership of another organization
                has_membership = OrganizationMember.objects.filter(
                    user=existing_user,
                    organization=self.organization,
                ).exists()
                if has_membership:
                    if not auth.login(request, existing_user,
                                      after_2fa=request.build_absolute_uri()):
                        return HttpResponseRedirect(auth.get_login_redirect(
                            self.request))
                    # assume they've confirmed they want to attach the identity
                    op = 'confirm'
                else:
                    # force them to create a new account
                    existing_user = None

            login_form = self._get_login_form(existing_user)
        elif request.user.is_managed:
            # per the above, try to auto merge if the user was originally an
            # SSO account but is still logged in
            has_membership = OrganizationMember.objects.filter(
                user=request.user,
                organization=self.organization,
            ).exists()
            if has_membership:
                # assume they've confirmed they want to attach the identity
                op = 'confirm'

        if op == 'confirm' and request.user.is_authenticated():
            auth_identity = self._handle_attach_identity(identity)
        elif op == 'newuser':
            auth_identity = self._handle_new_user(identity)
        elif op == 'login' and not request.user.is_authenticated():
            # confirm authentication, login
            op = None
            if login_form.is_valid():
                # This flow is special.  If we are going through a 2FA
                # flow here (login returns False) we want to instruct the
                # system to return upon completion of the 2fa flow to the
                # current URL and continue with the dialog.
                #
                # If there is no 2fa we don't need to do this and can just
                # go on.
                if not auth.login(request, login_form.get_user(),
                                  after_2fa=request.build_absolute_uri()):
                    return HttpResponseRedirect(auth.get_login_redirect(
                        self.request))
                request.session.pop('needs_captcha', None)
            else:
                auth.log_auth_failure(request, request.POST.get('username'))
                request.session['needs_captcha'] = 1
        else:
            op = None

        if not op:
            if request.user.is_authenticated():
                return self.respond('sentry/auth-confirm-link.html', {
                    'identity': identity,
                    'existing_user': request.user,
                    'identity_display_name': self._get_display_name(identity),
                    'identity_identifier': self._get_identifier(identity)
                })

            return self.respond('sentry/auth-confirm-identity.html', {
                'existing_user': existing_user,
                'identity': identity,
                'login_form': login_form,
                'identity_display_name': self._get_display_name(identity),
                'identity_identifier': self._get_identifier(identity)
            })

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        auth.login(self.request, user)

        self.clear_session()

        return HttpResponseRedirect(auth.get_login_redirect(self.request))
示例#41
0
def login_redirect(request):
    login_url = get_login_redirect(request)
    return HttpResponseRedirect(login_url)
示例#42
0
文件: helper.py 项目: rebeckag/sentry
    def _finish_login_pipeline(self, identity):
        """
        The login flow executes both with anonymous and authenticated users.

        Upon completion a few branches exist:

        If the identity is already linked, the user should be logged in
        and redirected immediately.

        Otherwise, the user is presented with a confirmation window. That window
        will show them the new account that will be created, and if they're
        already authenticated an optional button to associate the identity with
        their account.
        """
        auth_provider = self.auth_provider
        request = self.request

        try:
            auth_identity = AuthIdentity.objects.get(
                auth_provider=auth_provider,
                ident=identity['id'],
            )
        except AuthIdentity.DoesNotExist:
            if request.POST.get('op') == 'confirm' and request.user.is_authenticated():
                auth_identity = self._handle_attach_identity(identity)
            elif request.POST.get('op') == 'newuser':
                auth_identity = self._handle_new_user(identity)
            else:
                if request.user.is_authenticated():
                    return self.respond('sentry/auth-confirm-link.html', {
                        'identity': identity,
                    })
                return self.respond('sentry/auth-confirm-identity.html', {
                    'identity': identity,
                })
        else:
            # TODO(dcramer): this is very similar to attach
            now = timezone.now()
            auth_identity.update(
                data=identity.get('data', {}),
                last_verified=now,
                last_synced=now,
            )

            try:
                member = OrganizationMember.objects.get(
                    user=auth_identity.user,
                    organization=self.organization,
                )
            except OrganizationMember.DoesNotExist:
                # this is likely the case when someone was removed from the org
                # but still has access to rejoin
                member = self._handle_new_membership(auth_identity)
            else:
                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()

        user = auth_identity.user
        user.backend = settings.AUTHENTICATION_BACKENDS[0]

        login(self.request, user)

        self.clear_session()

        return HttpResponseRedirect(get_login_redirect(self.request))
示例#43
0
    def handle_basic_auth(self, request, **kwargs):
        can_register = self.can_register(request)

        op = request.POST.get("op")
        organization = kwargs.pop("organization", None)

        if not op:
            # Detect that we are on the register page by url /register/ and
            # then activate the register tab by default.
            if "/register" in request.path_info and can_register:
                op = "register"
            elif request.GET.get("op") == "sso":
                op = "sso"

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(
                request, initial={"username": request.session.get("invite_email", "")}
            )
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)
            user_signup.send_robust(
                sender=self, user=user, source="register-form", referrer="in-app"
            )

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

            auth.login(request, user, organization_id=organization.id if organization else None)

            # can_register should only allow a single registration
            request.session.pop("can_register", None)
            request.session.pop("invite_email", None)

            # In single org mode, associate the user to the orgnaization
            if settings.SENTRY_SINGLE_ORGANIZATION:
                organization = Organization.get_default()
                OrganizationMember.objects.create(
                    organization=organization, role=organization.default_role, user=user
                )

            # Attempt to directly accept any pending invites
            invite_helper = ApiInviteHelper.from_cookie(request=request, instance=self)

            if invite_helper and invite_helper.valid_request:
                invite_helper.accept_invite()
                response = self.redirect_to_org(request)
                remove_invite_cookie(request, response)

                return response

            return self.redirect(auth.get_login_redirect(request))

        elif request.method == "POST":
            from sentry.app import ratelimiter
            from sentry.utils.hashlib import md5_text

            login_attempt = (
                op == "login" and request.POST.get("username") and request.POST.get("password")
            )

            if login_attempt and ratelimiter.is_limited(
                u"auth:login:username:{}".format(
                    md5_text(login_form.clean_username(request.POST["username"])).hexdigest()
                ),
                limit=10,
                window=60,  # 10 per minute should be enough for anyone
            ):
                login_form.errors["__all__"] = [
                    u"You have made too many login attempts. Please try again later."
                ]
                metrics.incr(
                    "login.attempt", instance="rate_limited", skip_internal=True, sample_rate=1.0
                )
            elif login_form.is_valid():
                user = login_form.get_user()

                auth.login(request, user, organization_id=organization.id if organization else None)
                metrics.incr(
                    "login.attempt", instance="success", skip_internal=True, sample_rate=1.0
                )

                if not user.is_active:
                    return self.redirect(reverse("sentry-reactivate-account"))

                return self.redirect(auth.get_login_redirect(request))
            else:
                metrics.incr(
                    "login.attempt", instance="failure", skip_internal=True, sample_rate=1.0
                )

        context = {
            "op": op or "login",
            "server_hostname": get_server_hostname(),
            "login_form": login_form,
            "organization": organization,
            "register_form": register_form,
            "CAN_REGISTER": can_register,
            "join_request_link": self.get_join_request_link(organization),
        }
        context.update(additional_context.run_callbacks(request))

        return self.respond_login(request, context, **kwargs)
示例#44
0
    def handle_basic_auth(self, request, organization=None, *args, **kwargs):
        can_register = self.can_register(request,
                                         organization=organization,
                                         *args,
                                         **kwargs)

        op = request.POST.get('op')

        if not op:
            # Detect that we are on the register page by url /register/ and
            # then activate the register tab by default.
            if '/register' in request.path_info and can_register:
                op = 'register'
            elif request.GET.get('op') == 'sso':
                op = 'sso'

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(
                request,
                initial={'username': request.session.get('invite_email', '')})
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

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

            auth.login(
                request,
                user,
                organization_id=organization.id if organization else None,
            )

            # can_register should only allow a single registration
            request.session.pop('can_register', None)
            request.session.pop('invite_email', None)

            return self.redirect(auth.get_login_redirect(request))

        elif request.method == 'POST':
            from sentry.app import ratelimiter
            from sentry.utils.hashlib import md5_text

            login_attempt = op == 'login' and request.POST.get(
                'username') and request.POST.get('password')

            if login_attempt and ratelimiter.is_limited(
                    u'auth:login:username:{}'.format(
                        md5_text(
                            request.POST['username'].lower()).hexdigest()),
                    limit=10,
                    window=60,  # 10 per minute should be enough for anyone
            ):
                login_form.errors['__all__'] = [
                    u'You have made too many login attempts. Please try again later.'
                ]
                metrics.incr('login.attempt',
                             instance='rate_limited',
                             skip_internal=True,
                             sample_rate=1.0)
            elif login_form.is_valid():
                user = login_form.get_user()

                auth.login(
                    request,
                    user,
                    organization_id=organization.id if organization else None,
                )
                metrics.incr('login.attempt',
                             instance='success',
                             skip_internal=True,
                             sample_rate=1.0)

                if not user.is_active:
                    return self.redirect(reverse('sentry-reactivate-account'))

                return self.redirect(auth.get_login_redirect(request))
            else:
                metrics.incr('login.attempt',
                             instance='failure',
                             skip_internal=True,
                             sample_rate=1.0)

        context = {
            'op': op or 'login',
            'server_hostname': get_server_hostname(),
            'login_form': login_form,
            'organization': organization,
            'register_form': register_form,
            'CAN_REGISTER': can_register,
        }
        context.update(additional_context.run_callbacks(request))

        return self.respond_login(request,
                                  context,
                                  organization=organization,
                                  *args,
                                  **kwargs)
示例#45
0
文件: tests.py 项目: Kayle009/sentry
 def test_no_value_uses_default(self):
     result = get_login_redirect(self.make_request())
     assert result == reverse('sentry-login')
示例#46
0
    def handle_basic_auth(self, request):
        can_register = features.has('auth:register') or request.session.get('can_register')

        op = request.POST.get('op')

        # Detect that we are on the register page by url /register/ and
        # then activate the register tab by default.
        if not op and '/register' in request.path_info and can_register:
            op = 'register'

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(request)
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

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

            auth.login(request, user)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)

            request.session.pop('needs_captcha', None)

            return self.redirect(auth.get_login_redirect(request))

        elif login_form.is_valid():
            user = login_form.get_user()

            auth.login(request, user)

            request.session.pop('needs_captcha', None)

            if not user.is_active:
                return self.redirect(reverse('sentry-reactivate-account'))

            return self.redirect(auth.get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            auth.log_auth_failure(request, request.POST.get('username'))
            request.session['needs_captcha'] = 1
            login_form = self.get_login_form(request)
            login_form.errors.pop('captcha', None)
            if can_register:
                register_form = self.get_register_form(request)
                register_form.errors.pop('captcha', None)

        # When the captcha fails, hide any other errors
        # to prevent brute force attempts.
        if 'captcha' in login_form.errors:
            for k in login_form.errors.keys():
                if k != 'captcha':
                    login_form.errors.pop(k)

        request.session.set_test_cookie()

        context = {
            'op': op or 'login',
            'server_hostname': get_server_hostname(),
            'login_form': login_form,
            'register_form': register_form,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/login.html', context)
示例#47
0
 def handle(self, request):
     rv = get_login_redirect(request)
     logout(request)
     request.user = AnonymousUser()
     return self.redirect(rv)
示例#48
0
 def get_post_register_url(self, request):
     base_url = auth.get_login_redirect(request)
     params = {"frontend_events": json.dumps({"event_name": "Sign Up"})}
     return add_params_to_url(base_url, params)
示例#49
0
def login_redirect(request):
    login_url = auth.get_login_redirect(request)
    return HttpResponseRedirect(login_url)
示例#50
0
 def test_schema_uses_default(self):
     result = get_login_redirect(self.make_request('http://example.com'))
     assert result == reverse('sentry-login')
示例#51
0
    def handle_basic_auth(self, request, organization=None, *args, **kwargs):
        can_register = self.can_register(
            request, organization=organization, *args, **kwargs)

        op = request.POST.get('op')

        # Detect that we are on the register page by url /register/ and
        # then activate the register tab by default.
        if not op and '/register' in request.path_info and can_register:
            op = 'register'

        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(
                request, initial={
                    'username': request.session.get('invite_email', '')}
            )
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

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

            auth.login(
                request,
                user,
                organization_id=organization.id if organization else None,
            )

            # can_register should only allow a single registration
            request.session.pop('can_register', None)
            request.session.pop('invite_email', None)

            return self.redirect(auth.get_login_redirect(request))

        elif request.method == 'POST':
            from sentry.app import ratelimiter
            from sentry.utils.hashlib import md5_text

            login_attempt = op == 'login' and request.POST.get('username'
                                                               ) and request.POST.get('password')

            if login_attempt and ratelimiter.is_limited(
                u'auth:login:username:{}'.
                format(md5_text(request.POST['username'].lower()).hexdigest()),
                limit=10,
                window=60,  # 10 per minute should be enough for anyone
            ):
                login_form.errors['__all__'] = [
                    u'You have made too many login attempts. Please try again later.'
                ]
            elif login_form.is_valid():
                user = login_form.get_user()

                auth.login(
                    request,
                    user,
                    organization_id=organization.id if organization else None,
                )

                if not user.is_active:
                    return self.redirect(reverse('sentry-reactivate-account'))

                return self.redirect(auth.get_login_redirect(request))

        context = {
            'op': op or 'login',
            'server_hostname': get_server_hostname(),
            'login_form': login_form,
            'organization': organization,
            'register_form': register_form,
            'CAN_REGISTER': can_register,
        }
        return self.respond_login(request, context, organization=organization, *args, **kwargs)
    def handle_basic_auth(self, request, organization):
        can_register = features.has('auth:register') or request.session.get('can_register')

        op = request.POST.get('op')
        login_form = self.get_login_form(request)
        if can_register:
            register_form = self.get_register_form(request)
        else:
            register_form = None

        if can_register and register_form.is_valid():
            user = register_form.save()
            user.send_confirm_emails(is_new_user=True)

            defaults = {
                'role': 'member',
            }

            organization.member_set.create(
                user=user,
                **defaults
            )

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

            auth.login(request, user)

            # can_register should only allow a single registration
            request.session.pop('can_register', None)

            request.session.pop('needs_captcha', None)

            return self.redirect(auth.get_login_redirect(request))

        elif login_form.is_valid():
            auth.login(request, login_form.get_user())

            request.session.pop('needs_captcha', None)

            return self.redirect(auth.get_login_redirect(request))

        elif request.POST and not request.session.get('needs_captcha'):
            auth.log_auth_failure(request, request.POST.get('username'))
            request.session['needs_captcha'] = 1
            login_form = self.get_login_form(request)
            login_form.errors.pop('captcha', None)
            if can_register:
                register_form = self.get_register_form(request)
                register_form.errors.pop('captcha', None)

        # When the captcha fails, hide any other errors
        # to prevent brute force attempts.
        if 'captcha' in login_form.errors:
            for k in login_form.errors.keys():
                if k != 'captcha':
                    login_form.errors.pop(k)

        request.session.set_test_cookie()

        context = {
            'op': op or 'login',
            'login_form': login_form,
            'register_form': register_form,
            'organization': organization,
            'CAN_REGISTER': can_register,
        }
        return self.respond('sentry/organization-login.html', context)