예제 #1
0
파일: base.py 프로젝트: ForkRepo/sentry
 def handle_auth_required(self, request, *args, **kwargs):
     auth.initiate_login(request, next_url=request.get_full_path())
     if "organization_slug" in kwargs:
         redirect_to = reverse("sentry-auth-organization", args=[kwargs["organization_slug"]])
     else:
         redirect_to = auth.get_login_url()
     return self.redirect(redirect_to)
예제 #2
0
 def handle_auth_required(self, request, *args, **kwargs):
     auth.initiate_login(request, next_url=request.get_full_path())
     if "organization_slug" in kwargs:
         redirect_to = reverse("sentry-auth-organization", args=[kwargs["organization_slug"]])
     else:
         redirect_to = auth.get_login_url()
     return self.redirect(redirect_to, headers={"X-Robots-Tag": "noindex, nofollow"})
예제 #3
0
    def get(self, request, *args, **kwargs):
        """
        Get context required to show a login page. Registration is handled elsewhere.
        """
        if request.user.is_authenticated:
            # if the user is a superuser, but not 'superuser authenticated' we
            # allow them to re-authenticate to gain superuser status
            if not request.user.is_superuser or is_active_superuser(request):
                return self.respond_authenticated(request)

        next_uri = self.get_next_uri(request)

        # we always reset the state on GET so you don't end up at an odd location
        auth.initiate_login(request, next_uri)

        # Auth login verifies the test cookie is set
        request.session.set_test_cookie()

        # Single org mode -- send them to the org-specific handler
        if settings.SENTRY_SINGLE_ORGANIZATION:
            org = Organization.get_default()
            return Response({
                "nextUri":
                reverse("sentry-auth-organization", args=[org.slug])
            })

        session_expired = "session_expired" in request.COOKIES
        payload = self.prepare_login_context(request, *args, **kwargs)
        response = Response(payload)

        if session_expired:
            response.delete_cookie("session_expired")

        return response
예제 #4
0
 def handle_auth_required(self, request, *args, **kwargs):
     auth.initiate_login(request, next_url=request.get_full_path())
     if 'organization_slug' in kwargs:
         redirect_to = reverse('sentry-auth-organization', args=[kwargs['organization_slug']])
     else:
         redirect_to = auth.get_login_url()
     return self.redirect(redirect_to, headers={'X-Robots-Tag': 'noindex, nofollow'})
예제 #5
0
 def wrapped(request, *args, **kwargs):
     if not is_active_superuser(request):
         if request.user.is_superuser:
             auth.initiate_login(request, next_url=request.get_full_path())
             return HttpResponseRedirect(auth.get_login_url())
         return render_to_response('sentry/missing_permissions.html', {}, request, status=400)
     return func(request, *args, **kwargs)
예제 #6
0
    def get(self, request, *args, **kwargs):
        next_uri = self.get_next_uri(request, *args, **kwargs)
        if request.user.is_authenticated():
            # if the user is a superuser, but not 'superuser authenticated'
            # we allow them to re-authenticate to gain superuser status
            if not request.user.is_superuser or is_active_superuser(request):
                return self.handle_authenticated(request, *args, **kwargs)

        request.session.set_test_cookie()

        # we always reset the state on GET so you dont end up at an odd location
        auth.initiate_login(request, next_uri)

        # Single org mode -- send them to the org-specific handler
        if settings.SENTRY_SINGLE_ORGANIZATION:
            org = Organization.get_default()
            next_uri = reverse('sentry-auth-organization', args=[org.slug])
            return HttpResponseRedirect(next_uri)

        session_expired = 'session_expired' in request.COOKIES
        if session_expired:
            messages.add_message(request, messages.WARNING,
                                 WARN_SESSION_EXPIRED)

        response = self.handle_basic_auth(request, *args, **kwargs)

        if session_expired:
            response.delete_cookie('session_expired')

        return response
예제 #7
0
    def get(self, request, **kwargs):
        next_uri = self.get_next_uri(request)
        if request.user.is_authenticated():
            # if the user is a superuser, but not 'superuser authenticated'
            # we allow them to re-authenticate to gain superuser status
            if not request.user.is_superuser or is_active_superuser(request):
                return self.handle_authenticated(request)

        request.session.set_test_cookie()

        # we always reset the state on GET so you dont end up at an odd location
        auth.initiate_login(request, next_uri)

        # Single org mode -- send them to the org-specific handler
        if settings.SENTRY_SINGLE_ORGANIZATION:
            org = Organization.get_default()
            next_uri = reverse("sentry-auth-organization", args=[org.slug])
            return HttpResponseRedirect(next_uri)

        session_expired = "session_expired" in request.COOKIES
        if session_expired:
            messages.add_message(request, messages.WARNING, WARN_SESSION_EXPIRED)

        response = self.handle_basic_auth(request, **kwargs)

        if session_expired:
            response.delete_cookie("session_expired")

        return response
    def get(self, request, member_id, token):
        try:
            helper = self.get_helper(request, member_id, token)
        except OrganizationMember.DoesNotExist:
            return self.respond_invalid(request)

        if not helper.member_pending or not helper.valid_token:
            return self.respond_invalid(request)

        om = helper.om
        organization = om.organization

        # Keep track of the invite email for when we land back on the login page
        request.session["invite_email"] = om.email

        try:
            auth_provider = AuthProvider.objects.get(organization=organization)
        except AuthProvider.DoesNotExist:
            auth_provider = None

        data = {
            "orgSlug": organization.slug,
            "needsAuthentication": not helper.user_authenticated,
            "needs2fa": helper.needs_2fa,
            "needsSso": auth_provider is not None,
            # If they're already a member of the organization its likely
            # they're using a shared account and either previewing this invite
            # or are incorrectly expecting this to create a new account.
            "existingMember": helper.member_already_exists,
        }

        response = Response(None)

        # Allow users to register an account when accepting an invite
        if not helper.user_authenticated:
            request.session["can_register"] = True
            add_invite_cookie(request, response, member_id, token)

            # When SSO is required do *not* set a next_url to return to accept
            # invite. The invite will be accepted after SSO is completed.
            url = (reverse("sentry-accept-invite", args=[member_id, token])
                   if not auth_provider else "/")
            auth.initiate_login(self.request, next_url=url)

        # If the org has SSO setup, we'll store the invite cookie to later
        # associate the org member after authentication. We can avoid needing
        # to come back to the accept invite page since 2FA will *not* be
        # required if SSO is required.
        if auth_provider is not None:
            add_invite_cookie(request, response, member_id, token)
            provider = auth_provider.get_provider()
            data["ssoProvider"] = provider.name

        if helper.needs_2fa:
            add_invite_cookie(request, response, member_id, token)

        response.data = data

        return response
예제 #9
0
 def handle_auth_required(self, request, *args, **kwargs):
     from sentry.utils import auth  # Django 1.9 setup issue
     auth.initiate_login(request, next_url=request.get_full_path())
     if 'organization_slug' in kwargs:
         redirect_to = reverse('sentry-auth-organization',
                               args=[kwargs['organization_slug']])
     else:
         redirect_to = auth.get_login_url()
     return self.redirect(redirect_to)
예제 #10
0
 def wrapped(request, *args, **kwargs):
     if not request.user.is_authenticated():
         auth.initiate_login(request, next_url=request.get_full_path())
         if 'organization_slug' in kwargs:
             redirect_uri = reverse('sentry-auth-organization',
                                    args=[kwargs['organization_slug']])
         else:
             redirect_uri = auth.get_login_url()
         return HttpResponseRedirect(redirect_uri)
     return func(request, *args, **kwargs)
예제 #11
0
 def wrapped(request, *args, **kwargs):
     if not request.user.is_authenticated():
         auth.initiate_login(request, next_url=request.get_full_path())
         if "organization_slug" in kwargs:
             redirect_uri = reverse("sentry-auth-organization",
                                    args=[kwargs["organization_slug"]])
         else:
             redirect_uri = auth.get_login_url()
         return HttpResponseRedirect(redirect_uri)
     return func(request, *args, **kwargs)
예제 #12
0
 def handle_permission_required(self, request, organization, *args, **kwargs):
     if self.needs_sso(request, organization):
         logger.info(
             "access.must-sso",
             extra={"organization_id": organization.id, "user_id": request.user.id},
         )
         auth.initiate_login(request, next_url=request.get_full_path())
         redirect_uri = reverse("sentry-auth-organization", args=[organization.slug])
     else:
         redirect_uri = self.get_no_permission_url(request, *args, **kwargs)
     return self.redirect(redirect_uri)
예제 #13
0
 def handle_permission_required(self, request, organization, *args, **kwargs):
     if self.needs_sso(request, organization):
         logger.info('access.must-sso', extra={
             'organization_id': organization.id,
             'user_id': request.user.id,
         })
         auth.initiate_login(request, next_url=request.get_full_path())
         redirect_uri = reverse('sentry-auth-organization',
                                args=[organization.slug])
     else:
         redirect_uri = self.get_no_permission_url(request, *args, **kwargs)
     return self.redirect(redirect_uri)
예제 #14
0
 def handle_permission_required(self, request, organization, *args,
                                **kwargs):
     from sentry.utils import auth  # Django 1.9 setup issue
     if self.needs_sso(request, organization):
         logger.info('access.must-sso',
                     extra={
                         'organization_id': organization.id,
                         'user_id': request.user.id,
                     })
         auth.initiate_login(request, next_url=request.get_full_path())
         redirect_uri = reverse('sentry-auth-organization',
                                args=[organization.slug])
     else:
         redirect_uri = self.get_no_permission_url(request, *args, **kwargs)
     return self.redirect(redirect_uri)
예제 #15
0
파일: base.py 프로젝트: ForkRepo/sentry
    def handle_permission_required(self, request, organization, *args, **kwargs):
        needs_link = (
            organization
            and request.user.is_authenticated()
            and self.valid_sso_required
            and not request.access.sso_is_valid
        )

        auth.initiate_login(request, next_url=request.get_full_path())

        if needs_link:
            messages.add_message(request, messages.ERROR, ERR_MISSING_SSO_LINK)
            redirect_uri = reverse("sentry-auth-organization", args=[organization.slug])
        else:
            redirect_uri = self.get_no_permission_url(request, *args, **kwargs)
        return self.redirect(redirect_uri)
    def get(self, request, member_id, token):
        try:
            helper = self.get_helper(request, member_id, token)
        except OrganizationMember.DoesNotExist:
            return self.respond_invalid(request)

        if not helper.member_pending or not helper.valid_token:
            return self.respond_invalid(request)

        om = helper.om
        organization = om.organization

        # Keep track of the invite email for when we land back on the login page
        request.session["invite_email"] = om.email

        try:
            auth_provider = AuthProvider.objects.get(organization=organization)
        except AuthProvider.DoesNotExist:
            auth_provider = None

        data = {
            "orgSlug": organization.slug,
            "needsAuthentication": not helper.user_authenticated,
            "needs2fa": helper.needs_2fa,
            "needsSso": auth_provider is not None,
            # If they're already a member of the organization its likely
            # they're using a shared account and either previewing this invite
            # or are incorrectly expecting this to create a new account.
            "existingMember": helper.member_already_exists,
        }

        if auth_provider is not None:
            provider = auth_provider.get_provider()
            data["ssoProvider"] = provider.name

        # Allow users to register an account when accepting an invite
        if not helper.user_authenticated:
            url = reverse("sentry-accept-invite", args=[member_id, token])
            auth.initiate_login(self.request, next_url=url)
            request.session["can_register"] = True

        response = Response(data)

        if helper.needs_2fa:
            helper.add_invite_cookie(request, response, member_id, token)

        return response
예제 #17
0
파일: base.py 프로젝트: yuvrajm/sentry
    def handle_permission_required(self, request, organization, *args, **kwargs):
        needs_link = (
            organization and request.user.is_authenticated()
            and self.valid_sso_required and not request.access.sso_is_valid
        )

        auth.initiate_login(request, next_url=request.get_full_path())

        if needs_link:
            messages.add_message(
                request, messages.ERROR,
                ERR_MISSING_SSO_LINK,
            )
            redirect_uri = reverse('sentry-auth-organization',
                                   args=[organization.slug])
        else:
            redirect_uri = self.get_no_permission_url(request, *args, **kwargs)
        return self.redirect(redirect_uri)
예제 #18
0
    def handle(self, request):
        next_uri = request.GET.get(REDIRECT_FIELD_NAME, None)
        if request.user.is_authenticated():
            if auth.is_valid_redirect(next_uri, host=request.get_host()):
                return self.redirect(next_uri)
            return self.redirect_to_org(request)

        request.session.set_test_cookie()

        if next_uri:
            auth.initiate_login(request, next_uri)

        # Single org mode -- send them to the org-specific handler
        if settings.SENTRY_SINGLE_ORGANIZATION:
            org = Organization.get_default()
            next_uri = reverse('sentry-auth-organization', args=[org.slug])
            return HttpResponseRedirect(next_uri)

        op = request.POST.get('op')
        if op == 'sso' and request.POST.get('organization'):
            auth_provider = self.get_auth_provider(
                request.POST['organization'])
            if auth_provider:
                next_uri = reverse('sentry-auth-organization',
                                   args=[request.POST['organization']])
            else:
                next_uri = request.path
                messages.add_message(request, messages.ERROR, ERR_NO_SSO)

            return HttpResponseRedirect(next_uri)

        session_expired = 'session_expired' in request.COOKIES
        if session_expired:
            messages.add_message(request, messages.WARNING,
                                 WARN_SESSION_EXPIRED)

        response = self.handle_basic_auth(request)

        if session_expired:
            response.delete_cookie('session_expired')

        return response
예제 #19
0
    def handle(self, request):
        next_uri = request.GET.get('next', None)
        if request.user.is_authenticated():
            if auth.is_valid_redirect(next_uri):
                return self.redirect(next_uri)
            return self.redirect_to_org(request)

        request.session.set_test_cookie()

        if next_uri:
            auth.initiate_login(request, next_uri)

        # Single org mode -- send them to the org-specific handler
        if settings.SENTRY_SINGLE_ORGANIZATION:
            org = Organization.get_default()
            next_uri = reverse('sentry-auth-organization',
                               args=[org.slug])
            return HttpResponseRedirect(next_uri)

        op = request.POST.get('op')
        if op == 'sso' and request.POST.get('organization'):
            auth_provider = self.get_auth_provider(request.POST['organization'])
            if auth_provider:
                next_uri = reverse('sentry-auth-organization',
                                   args=[request.POST['organization']])
            else:
                next_uri = request.path
                messages.add_message(request, messages.ERROR, ERR_NO_SSO)

            return HttpResponseRedirect(next_uri)

        session_expired = 'session_expired' in request.COOKIES
        if session_expired:
            messages.add_message(request, messages.WARNING, WARN_SESSION_EXPIRED)

        response = self.handle_basic_auth(request)

        if session_expired:
            response.delete_cookie('session_expired')

        return response
    def handle(self, request, member_id, token):
        assert request.method in ('POST', 'GET')

        try:
            helper = WebInviteHelper(
                instance=self,
                request=request,
                member_id=member_id,
                token=token
            )
        except OrganizationMember.DoesNotExist:
            return self.redirect_with_err_message(request)

        if not helper.member_pending or not helper.valid_token:
            return self.redirect_with_err_message(request)

        om = helper.om
        organization = om.organization

        qs = Project.objects.filter(
            organization=organization,
        )
        project_list = list(qs[:25])
        project_count = qs.count()

        context = {
            'org_name': organization.name,
            'project_list': project_list,
            'project_count': project_count,
            'needs_authentication': not helper.user_authenticated,
            'needs_2fa': helper.needs_2fa,
            'logout_url': u'{}?next={}'.format(
                reverse('sentry-logout'),
                request.path,
            ),
            'login_url': u'{}?next={}'.format(
                reverse('sentry-login'),
                request.path,
            ),
            'register_url': u'{}?next={}'.format(
                reverse('sentry-register'),
                request.path,
            ),
        }

        if not helper.user_authenticated:
            # Show login or register form
            auth.initiate_login(request, next_url=request.get_full_path())
            request.session['can_register'] = True
            request.session['invite_email'] = om.email

            return self.respond('sentry/accept-organization-invite.html', context)

        if helper.needs_2fa:
            # redirect to setup 2fa
            response = self.respond('sentry/accept-organization-invite.html', context)
            response.set_cookie(PENDING_INVITE, request.path, max_age=MAX_AGE)
            return response

        # if they're already a member of the organization its likely they're
        # using a shared account and either previewing this invite or
        # are incorrectly expecting this to create a new account for them
        context['existing_member'] = helper.member_already_exists

        form = self.get_form(request)
        if form.is_valid():
            helper.accept_invite()

            request.session.pop('can_register', None)
            response = self.redirect(reverse('sentry-organization-home', args=[organization.slug]))
            return helper.remove_invite_cookie(response)

        context['form'] = form
        return self.respond('sentry/accept-organization-invite.html', context)
예제 #21
0
    def put(self, request: Request):
        """
        Verify a User
        `````````````

        This endpoint verifies the currently authenticated user (for example, to gain superuser).

        :auth: required
        """
        if not request.user.is_authenticated:
            return Response(status=status.HTTP_401_UNAUTHORIZED)

        validator = AuthVerifyValidator(data=request.data)
        if not validator.is_valid():
            return self.respond(validator.errors,
                                status=status.HTTP_400_BAD_REQUEST)

        authenticated = False
        # See if we have a u2f challenge/response
        if "challenge" in validator.validated_data and "response" in validator.validated_data:
            try:
                interface = Authenticator.objects.get_interface(
                    request.user, "u2f")
                if not interface.is_enrolled():
                    raise LookupError()
                challenge = json.loads(validator.validated_data["challenge"])
                response = json.loads(validator.validated_data["response"])
                can_webauthn_signin = self.check_can_webauthn_signin(
                    request.user, request.user)
                authenticated = interface.validate_response(
                    request, challenge, response, can_webauthn_signin)
            except ValueError:
                pass
            except LookupError:
                pass

        # attempt password authentication
        else:
            authenticated = request.user.check_password(
                validator.validated_data["password"])

        # UI treats 401s by redirecting, this 401 should be ignored
        if not authenticated:
            return Response({"detail": {
                "code": "ignore"
            }},
                            status=status.HTTP_403_FORBIDDEN)

        try:
            # Must use the real request object that Django knows about
            auth.login(request._request, request.user)
        except auth.AuthUserPasswordExpired:
            return Response(
                {
                    "code":
                    "password-expired",
                    "message":
                    "Cannot sign-in with basic auth because password has expired.",
                },
                status=status.HTTP_403_FORBIDDEN,
            )

        if request.user.is_superuser and not is_active_superuser(
                request) and Superuser.org_id:
            # if a superuser hitting this endpoint is not active, they are most likely
            # trying to become active, and likely need to re-identify with SSO to do so.
            redirect = request.META.get("HTTP_REFERER", "")
            if not is_safe_url(redirect, allowed_hosts=(request.get_host(), )):
                redirect = None

            initiate_login(request, redirect)
            raise SsoRequired(
                Organization.objects.get_from_cache(id=Superuser.org_id))

        request.user = request._request.user

        return self.get(request)
    def handle(self, request, member_id, token):
        assert request.method in ('POST', 'GET')

        try:
            om = OrganizationMember.objects.get(pk=member_id)
        except OrganizationMember.DoesNotExist:
            messages.add_message(
                request, messages.ERROR,
                ERR_INVITE_INVALID,
            )

            return self.redirect(reverse('sentry'))

        if not om.is_pending:
            messages.add_message(
                request, messages.ERROR,
                ERR_INVITE_INVALID,
            )

            return self.redirect(reverse('sentry'))

        if not constant_time_compare(om.token or om.legacy_token, token):
            messages.add_message(
                request, messages.ERROR,
                ERR_INVITE_INVALID,
            )
            return self.redirect(reverse('sentry'))

        organization = om.organization

        qs = Project.objects.filter(
            organization=organization,
        )
        project_list = list(qs.select_related('team')[:25])
        project_count = qs.count()

        context = {
            'organization': om.organization,
            'project_list': project_list,
            'project_count': project_count,
            'needs_authentication': not request.user.is_authenticated(),
            'logout_url': '{}?next={}'.format(
                reverse('sentry-logout'),
                request.path,
            ),
            'login_url': '{}?next={}'.format(
                reverse('sentry-login'),
                request.path,
            ),
            'register_url': '{}?next={}'.format(
                reverse('sentry-register'),
                request.path,
            ),
        }

        if not request.user.is_authenticated():
            # Show login or register form
            auth.initiate_login(request, next_url=request.get_full_path())
            request.session['can_register'] = True
            request.session['invite_email'] = om.email

            return self.respond('sentry/accept-organization-invite.html', context)

        # if they're already a member of the organization its likely they're
        # using a shared account and either previewing this invite or
        # are incorrectly expecting this to create a new account for them
        context['existing_member'] = OrganizationMember.objects.filter(
            user=request.user.id,
            organization=om.organization_id,
        ).exists()

        form = self.get_form(request)
        if form.is_valid():
            if OrganizationMember.objects.filter(organization=organization, user=request.user).exists():
                messages.add_message(
                    request, messages.SUCCESS,
                    _('You are already a member of the %r organization.') % (
                        organization.name.encode('utf-8'),
                    )
                )

                om.delete()
            else:
                om.user = request.user
                om.email = None
                om.save()

                self.create_audit_entry(
                    request,
                    organization=organization,
                    target_object=om.id,
                    target_user=request.user,
                    event=AuditLogEntryEvent.MEMBER_ACCEPT,
                    data=om.get_audit_log_data(),
                )

                messages.add_message(
                    request, messages.SUCCESS,
                    _('You have been added to the %r organization.') % (
                        organization.name.encode('utf-8'),
                    )
                )

                member_joined.send(member=om, sender=self)

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

            return self.redirect(reverse('sentry-organization-home', args=[organization.slug]))

        context['form'] = form

        return self.respond('sentry/accept-organization-invite.html', context)
예제 #23
0
    def handle(self, request, member_id, token):
        assert request.method in ('POST', 'GET')

        try:
            om = OrganizationMember.objects.get(pk=member_id)
        except OrganizationMember.DoesNotExist:
            messages.add_message(
                request,
                messages.ERROR,
                ERR_INVITE_INVALID,
            )

            return self.redirect(reverse('sentry'))

        if not om.is_pending:
            messages.add_message(
                request,
                messages.ERROR,
                ERR_INVITE_INVALID,
            )

            return self.redirect(reverse('sentry'))

        if not constant_time_compare(om.token or om.legacy_token, token):
            messages.add_message(
                request,
                messages.ERROR,
                ERR_INVITE_INVALID,
            )
            return self.redirect(reverse('sentry'))

        organization = om.organization

        qs = Project.objects.filter(organization=organization, )
        project_list = list(qs[:25])
        project_count = qs.count()

        context = {
            'organization':
            om.organization,
            'project_list':
            project_list,
            'project_count':
            project_count,
            'needs_authentication':
            not request.user.is_authenticated(),
            'logout_url':
            '{}?next={}'.format(
                reverse('sentry-logout'),
                request.path,
            ),
            'login_url':
            '{}?next={}'.format(
                reverse('sentry-login'),
                request.path,
            ),
            'register_url':
            '{}?next={}'.format(
                reverse('sentry-register'),
                request.path,
            ),
        }

        if not request.user.is_authenticated():
            # Show login or register form
            auth.initiate_login(request, next_url=request.get_full_path())
            request.session['can_register'] = True
            request.session['invite_email'] = om.email

            return self.respond('sentry/accept-organization-invite.html',
                                context)

        # if they're already a member of the organization its likely they're
        # using a shared account and either previewing this invite or
        # are incorrectly expecting this to create a new account for them
        context['existing_member'] = OrganizationMember.objects.filter(
            user=request.user.id,
            organization=om.organization_id,
        ).exists()

        form = self.get_form(request)
        if form.is_valid():
            if OrganizationMember.objects.filter(organization=organization,
                                                 user=request.user).exists():
                messages.add_message(
                    request, messages.SUCCESS,
                    _('You are already a member of the %r organization.') %
                    (organization.name.encode('utf-8'), ))

                om.delete()
            else:
                om.user = request.user
                om.email = None
                om.save()

                self.create_audit_entry(
                    request,
                    organization=organization,
                    target_object=om.id,
                    target_user=request.user,
                    event=AuditLogEntryEvent.MEMBER_ACCEPT,
                    data=om.get_audit_log_data(),
                )

                messages.add_message(
                    request, messages.SUCCESS,
                    _('You have been added to the %r organization.') %
                    (organization.name.encode('utf-8'), ))

                member_joined.send(member=om, sender=self)

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

            return self.redirect(
                reverse('sentry-organization-home', args=[organization.slug]))

        context['form'] = form

        return self.respond('sentry/accept-organization-invite.html', context)
    def handle(self, request, member_id, token):
        assert request.method in ('POST', 'GET')

        try:
            helper = WebInviteHelper(instance=self,
                                     request=request,
                                     member_id=member_id,
                                     token=token)
        except OrganizationMember.DoesNotExist:
            return self.redirect_with_err_message(request)

        if not helper.member_pending or not helper.valid_token:
            return self.redirect_with_err_message(request)

        om = helper.om
        organization = om.organization

        context = {
            'org_name':
            organization.name,
            'needs_authentication':
            not helper.user_authenticated,
            'needs_2fa':
            helper.needs_2fa,
            'logout_url':
            u'{}?next={}'.format(
                reverse('sentry-logout'),
                request.path,
            ),
            'login_url':
            u'{}?next={}'.format(
                reverse('sentry-login'),
                request.path,
            ),
            'register_url':
            u'{}?next={}'.format(
                reverse('sentry-register'),
                request.path,
            ),
        }

        if not helper.user_authenticated:
            # Show login or register form
            auth.initiate_login(request, next_url=request.get_full_path())
            request.session['can_register'] = True
            request.session['invite_email'] = om.email

            return self.respond('sentry/accept-organization-invite.html',
                                context)

        if helper.needs_2fa:
            # redirect to setup 2fa
            response = self.respond('sentry/accept-organization-invite.html',
                                    context)
            response.set_cookie(PENDING_INVITE,
                                request.path,
                                max_age=COOKIE_MAX_AGE)
            return response

        # if they're already a member of the organization its likely they're
        # using a shared account and either previewing this invite or
        # are incorrectly expecting this to create a new account for them
        context['existing_member'] = helper.member_already_exists

        form = self.get_form(request)
        if form.is_valid():
            helper.accept_invite()

            request.session.pop('can_register', None)
            response = self.redirect(
                reverse('sentry-organization-home', args=[organization.slug]))
            return helper.remove_invite_cookie(response)

        context['form'] = form
        return self.respond('sentry/accept-organization-invite.html', context)
    def handle(self, request, member_id, token):
        assert request.method in ("POST", "GET")

        try:
            helper = WebInviteHelper(instance=self,
                                     request=request,
                                     member_id=member_id,
                                     token=token)
        except OrganizationMember.DoesNotExist:
            return self.redirect_with_err_message(request)

        if not helper.member_pending or not helper.valid_token:
            return self.redirect_with_err_message(request)

        om = helper.om
        organization = om.organization

        context = {
            "org_name":
            organization.name,
            "needs_authentication":
            not helper.user_authenticated,
            "needs_2fa":
            helper.needs_2fa,
            "logout_url":
            u"{}?next={}".format(reverse("sentry-logout"), request.path),
            "login_url":
            u"{}?next={}".format(reverse("sentry-login"), request.path),
            "register_url":
            u"{}?next={}".format(reverse("sentry-register"), request.path),
        }

        if not helper.user_authenticated:
            # Show login or register form
            auth.initiate_login(request, next_url=request.get_full_path())
            request.session["can_register"] = True
            request.session["invite_email"] = om.email

            return self.respond("sentry/accept-organization-invite.html",
                                context)

        if helper.needs_2fa:
            # redirect to setup 2fa
            response = self.respond("sentry/accept-organization-invite.html",
                                    context)
            response.set_cookie(PENDING_INVITE,
                                request.path,
                                max_age=COOKIE_MAX_AGE)
            return response

        # if they're already a member of the organization its likely they're
        # using a shared account and either previewing this invite or
        # are incorrectly expecting this to create a new account for them
        context["existing_member"] = helper.member_already_exists

        form = self.get_form(request)
        if form.is_valid():
            helper.accept_invite()

            request.session.pop("can_register", None)
            response = self.redirect(organization.get_url())
            return helper.remove_invite_cookie(response)

        context["form"] = form
        return self.respond("sentry/accept-organization-invite.html", context)