mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 14:35:27 +00:00
auth: Make multiuse invite link work with oAuth2.
This works by attaching to the user's session the multi-use invitation key, allowing that to be used in the Google/GitHub auth flows.
This commit is contained in:
@@ -23,6 +23,7 @@ from zerver.lib.actions import (
|
||||
do_reactivate_realm,
|
||||
do_reactivate_user,
|
||||
do_set_realm_authentication_methods,
|
||||
create_stream_if_needed,
|
||||
)
|
||||
from zerver.lib.mobile_auth_otp import otp_decrypt_api_key
|
||||
from zerver.lib.validator import validate_login_email, \
|
||||
@@ -36,9 +37,9 @@ from zerver.lib.test_classes import (
|
||||
from zerver.lib.test_helpers import POSTRequestMock
|
||||
from zerver.models import \
|
||||
get_realm, email_to_username, UserProfile, \
|
||||
PreregistrationUser, Realm, get_user
|
||||
PreregistrationUser, Realm, get_user, MultiuseInvite
|
||||
|
||||
from confirmation.models import Confirmation, confirmation_url
|
||||
from confirmation.models import Confirmation, confirmation_url, create_confirmation_link
|
||||
|
||||
from zproject.backends import ZulipDummyBackend, EmailAuthBackend, \
|
||||
GoogleMobileOauth2Backend, ZulipRemoteUserBackend, ZulipLDAPAuthBackend, \
|
||||
@@ -994,6 +995,69 @@ class GoogleSubdomainLoginTest(GoogleOAuthTest):
|
||||
self.assert_not_in_success_response(['id_password'], result)
|
||||
self.assert_in_success_response(['id_full_name'], result)
|
||||
|
||||
@override_settings(REALMS_HAVE_SUBDOMAINS=True)
|
||||
def test_log_into_subdomain_when_using_invite_link(self):
|
||||
# type: () -> None
|
||||
data = {'name': 'New User Name',
|
||||
'email': 'new@zulip.com',
|
||||
'subdomain': 'zulip',
|
||||
'is_signup': True}
|
||||
|
||||
realm = get_realm("zulip")
|
||||
realm.invite_required = True
|
||||
realm.save()
|
||||
|
||||
stream_names = ["new_stream_1", "new_stream_2"]
|
||||
streams = []
|
||||
for stream_name in set(stream_names):
|
||||
stream, _ = create_stream_if_needed(realm, stream_name)
|
||||
streams.append(stream)
|
||||
|
||||
self.client.cookies = SimpleCookie(self.get_signed_subdomain_cookie(data))
|
||||
|
||||
# Without the invite link, we can't create an account due to invite_required
|
||||
result = self.client_get('/accounts/login/subdomain/', subdomain="zulip")
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assert_in_success_response(['Sign up for Zulip'], result)
|
||||
|
||||
# Now confirm an invitation link works
|
||||
referrer = self.example_user("hamlet")
|
||||
multiuse_obj = MultiuseInvite.objects.create(realm=realm, referred_by=referrer)
|
||||
multiuse_obj.streams = streams
|
||||
multiuse_obj.save()
|
||||
invite_link = create_confirmation_link(multiuse_obj, realm.host,
|
||||
Confirmation.MULTIUSE_INVITE)
|
||||
|
||||
result = self.client_get(invite_link, subdomain="zulip")
|
||||
self.assert_in_success_response(['Sign up for Zulip'], result)
|
||||
|
||||
result = self.client_get('/accounts/login/subdomain/', subdomain="zulip")
|
||||
self.assertEqual(result.status_code, 302)
|
||||
|
||||
confirmation = Confirmation.objects.all().last()
|
||||
confirmation_key = confirmation.confirmation_key
|
||||
self.assertIn('do_confirm/' + confirmation_key, result.url)
|
||||
result = self.client_get(result.url)
|
||||
self.assert_in_response('action="/accounts/register/"', result)
|
||||
data2 = {"from_confirmation": "1",
|
||||
"full_name": data['name'],
|
||||
"key": confirmation_key}
|
||||
result = self.client_post('/accounts/register/', data2, subdomain="zulip")
|
||||
self.assert_in_response("You're almost there", result)
|
||||
|
||||
# Verify that the user is asked for name but not password
|
||||
self.assert_not_in_success_response(['id_password'], result)
|
||||
self.assert_in_success_response(['id_full_name'], result)
|
||||
|
||||
# Click confirm registration button.
|
||||
result = self.client_post(
|
||||
'/accounts/register/',
|
||||
{'full_name': 'New User Name',
|
||||
'key': confirmation_key,
|
||||
'terms': True})
|
||||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(sorted(self.get_streams('new@zulip.com', realm)), stream_names)
|
||||
|
||||
@override_settings(REALMS_HAVE_SUBDOMAINS=True)
|
||||
def test_log_into_subdomain_when_email_is_none(self):
|
||||
# type: () -> None
|
||||
|
||||
@@ -47,7 +47,19 @@ import ujson
|
||||
|
||||
def maybe_send_to_registration(request, email, full_name='', password_required=True):
|
||||
# type: (HttpRequest, Text, Text, bool) -> HttpResponse
|
||||
form = HomepageForm({'email': email}, realm=get_realm_from_request(request))
|
||||
|
||||
realm = get_realm_from_request(request)
|
||||
from_multiuse_invite = False
|
||||
multiuse_obj = None
|
||||
streams_to_subscribe = None
|
||||
multiuse_object_key = request.session.get("multiuse_object_key", None)
|
||||
if multiuse_object_key is not None:
|
||||
from_multiuse_invite = True
|
||||
multiuse_obj = Confirmation.objects.get(confirmation_key=multiuse_object_key).content_object
|
||||
realm = multiuse_obj.realm
|
||||
streams_to_subscribe = multiuse_obj.streams.all()
|
||||
|
||||
form = HomepageForm({'email': email}, realm=realm, from_multiuse_invite=from_multiuse_invite)
|
||||
request.verified_email = None
|
||||
if form.is_valid():
|
||||
# Construct a PreregistrationUser object and send the user over to
|
||||
@@ -63,6 +75,13 @@ def maybe_send_to_registration(request, email, full_name='', password_required=T
|
||||
prereg_user = create_preregistration_user(email, request,
|
||||
password_required=password_required)
|
||||
|
||||
if multiuse_object_key is not None:
|
||||
del request.session["multiuse_object_key"]
|
||||
request.session.modified = True
|
||||
if streams_to_subscribe is not None:
|
||||
prereg_user.streams = streams_to_subscribe
|
||||
prereg_user.save()
|
||||
|
||||
return redirect("".join((
|
||||
create_confirmation_link(prereg_user, request.get_host(), Confirmation.USER_REGISTRATION),
|
||||
'?full_name=',
|
||||
@@ -73,7 +92,8 @@ def maybe_send_to_registration(request, email, full_name='', password_required=T
|
||||
url = reverse('register')
|
||||
return render(request,
|
||||
'zerver/accounts_home.html',
|
||||
context={'form': form, 'current_url': lambda: url},
|
||||
context={'form': form, 'current_url': lambda: url,
|
||||
'from_multiuse_invite': from_multiuse_invite},
|
||||
)
|
||||
|
||||
def redirect_to_subdomain_login_url():
|
||||
|
||||
@@ -402,6 +402,8 @@ def accounts_home_from_multiuse_invite(request, confirmation_key):
|
||||
multiuse_object = None
|
||||
try:
|
||||
multiuse_object = get_object_from_key(confirmation_key)
|
||||
# Required for oAuth2
|
||||
request.session["multiuse_object_key"] = confirmation_key
|
||||
except ConfirmationKeyException as exception:
|
||||
realm = get_realm_from_request(request)
|
||||
if realm is None or realm.invite_required:
|
||||
|
||||
Reference in New Issue
Block a user