invite: Fix invitations removed from list too soon.

On invitations panel, invites were being removed when
the user clicked on invitation's link. Now we only remove
it when the user completes registration.

Fixes: #12281
This commit is contained in:
arunikaydav42 2020-02-15 11:36:48 +05:30 committed by Tim Abbott
parent de00c3cd6a
commit 4680d504de
5 changed files with 43 additions and 10 deletions

View File

@ -43,7 +43,8 @@ def generate_key() -> str:
ConfirmationObjT = Union[MultiuseInvite, PreregistrationUser, EmailChangeStatus] ConfirmationObjT = Union[MultiuseInvite, PreregistrationUser, EmailChangeStatus]
def get_object_from_key(confirmation_key: str, def get_object_from_key(confirmation_key: str,
confirmation_type: int) -> ConfirmationObjT: confirmation_type: int,
activate_object: bool=True) -> ConfirmationObjT:
# Confirmation keys used to be 40 characters # Confirmation keys used to be 40 characters
if len(confirmation_key) not in (24, 40): if len(confirmation_key) not in (24, 40):
raise ConfirmationKeyException(ConfirmationKeyException.WRONG_LENGTH) raise ConfirmationKeyException(ConfirmationKeyException.WRONG_LENGTH)
@ -58,7 +59,7 @@ def get_object_from_key(confirmation_key: str,
raise ConfirmationKeyException(ConfirmationKeyException.EXPIRED) raise ConfirmationKeyException(ConfirmationKeyException.EXPIRED)
obj = confirmation.content_object obj = confirmation.content_object
if hasattr(obj, "status"): if activate_object and hasattr(obj, "status"):
obj.status = getattr(settings, 'STATUS_ACTIVE', 1) obj.status = getattr(settings, 'STATUS_ACTIVE', 1)
obj.save(update_fields=['status']) obj.save(update_fields=['status'])
return obj return obj

View File

@ -362,6 +362,8 @@ def process_new_human_user(user_profile: UserProfile,
realm_creation: bool=False) -> None: realm_creation: bool=False) -> None:
mit_beta_user = user_profile.realm.is_zephyr_mirror_realm mit_beta_user = user_profile.realm.is_zephyr_mirror_realm
if prereg_user is not None: if prereg_user is not None:
prereg_user.status = confirmation_settings.STATUS_ACTIVE
prereg_user.save(update_fields=['status'])
streams = prereg_user.streams.all() streams = prereg_user.streams.all()
acting_user: Optional[UserProfile] = prereg_user.referred_by acting_user: Optional[UserProfile] = prereg_user.referred_by
else: else:

View File

@ -418,7 +418,8 @@ class ZulipTestCase(TestCase):
from_confirmation: Optional[str]='', full_name: Optional[str]=None, from_confirmation: Optional[str]='', full_name: Optional[str]=None,
timezone: Optional[str]='', realm_in_root_domain: Optional[str]=None, timezone: Optional[str]='', realm_in_root_domain: Optional[str]=None,
default_stream_groups: Optional[List[str]]=[], default_stream_groups: Optional[List[str]]=[],
source_realm: Optional[str]='', **kwargs: Any) -> HttpResponse: source_realm: Optional[str]='',
key: Optional[str]=None, **kwargs: Any) -> HttpResponse:
""" """
Stage two of the two-step registration process. Stage two of the two-step registration process.
@ -429,13 +430,12 @@ class ZulipTestCase(TestCase):
""" """
if full_name is None: if full_name is None:
full_name = email.replace("@", "_") full_name = email.replace("@", "_")
payload = { payload = {
'full_name': full_name, 'full_name': full_name,
'password': password, 'password': password,
'realm_name': realm_name, 'realm_name': realm_name,
'realm_subdomain': realm_subdomain, 'realm_subdomain': realm_subdomain,
'key': find_key_by_email(email), 'key': key if key is not None else find_key_by_email(email),
'timezone': timezone, 'timezone': timezone,
'terms': True, 'terms': True,
'from_confirmation': from_confirmation, 'from_confirmation': from_confirmation,

View File

@ -33,6 +33,7 @@ from zerver.models import (
CustomProfileFieldValue, DefaultStream, PreregistrationUser, CustomProfileFieldValue, DefaultStream, PreregistrationUser,
Realm, Recipient, Message, ScheduledEmail, UserProfile, UserMessage, Realm, Recipient, Message, ScheduledEmail, UserProfile, UserMessage,
Stream, Subscription, flush_per_request_caches, get_system_bot, Stream, Subscription, flush_per_request_caches, get_system_bot,
get_user_by_delivery_email
) )
from zerver.lib.actions import ( from zerver.lib.actions import (
do_change_user_role, do_change_user_role,
@ -40,8 +41,7 @@ from zerver.lib.actions import (
do_create_default_stream_group, do_create_default_stream_group,
do_add_default_stream, do_add_default_stream,
do_create_realm, do_create_realm,
get_default_streams_for_realm, get_default_streams_for_realm)
)
from zerver.lib.send_email import send_future_email, FromAddress, \ from zerver.lib.send_email import send_future_email, FromAddress, \
deliver_email deliver_email
from zerver.lib.initial_password import initial_password from zerver.lib.initial_password import initial_password
@ -604,7 +604,7 @@ class LoginTest(ZulipTestCase):
with queries_captured() as queries: with queries_captured() as queries:
self.register(self.nonreg_email('test'), "test") self.register(self.nonreg_email('test'), "test")
# Ensure the number of queries we make is not O(streams) # Ensure the number of queries we make is not O(streams)
self.assertEqual(len(queries), 77) self.assertEqual(len(queries), 78)
user_profile = self.nonreg_user('test') user_profile = self.nonreg_user('test')
self.assert_logged_in_user_id(user_profile.id) self.assert_logged_in_user_id(user_profile.id)
self.assertFalse(user_profile.enable_stream_desktop_notifications) self.assertFalse(user_profile.enable_stream_desktop_notifications)
@ -1749,6 +1749,37 @@ class InvitationsTestCase(InviteUserBase):
error_result = self.client_delete('/json/invites/' + str(prereg_user.id)) error_result = self.client_delete('/json/invites/' + str(prereg_user.id))
self.assert_json_error(error_result, "No such invitation") self.assert_json_error(error_result, "No such invitation")
def test_prereg_user_status(self) -> None:
email = self.nonreg_email("alice")
password = "password"
realm = get_realm('zulip')
inviter = UserProfile.objects.first()
prereg_user = PreregistrationUser.objects.create(
email=email, referred_by=inviter, realm=realm)
confirmation_link = create_confirmation_link(prereg_user, 'host', Confirmation.USER_REGISTRATION)
registration_key = confirmation_link.split('/')[-1]
result = self.client_post(
"/accounts/register/",
{"key": registration_key,
"from_confirmation": "1",
"full_name": "alice"})
self.assertEqual(result.status_code, 200)
confirmation = Confirmation.objects.get(confirmation_key=registration_key)
prereg_user = confirmation.content_object
self.assertEqual(prereg_user.status, 0)
result = self.submit_reg_form_for_user(email, password, key=registration_key)
self.assertEqual(result.status_code, 302)
prereg_user = PreregistrationUser.objects.get(
email=email, referred_by=inviter, realm=realm)
self.assertEqual(prereg_user.status, confirmation_settings.STATUS_ACTIVE)
user = get_user_by_delivery_email(email, realm)
self.assertIsNotNone(user)
self.assertEqual(user.delivery_email, email)
class InviteeEmailsParserTests(TestCase): class InviteeEmailsParserTests(TestCase):
def setUp(self) -> None: def setUp(self) -> None:
super().setUp() super().setUp()

View File

@ -56,7 +56,7 @@ def check_prereg_key_and_redirect(request: HttpRequest, confirmation_key: str) -
return render_confirmation_key_error( return render_confirmation_key_error(
request, ConfirmationKeyException(ConfirmationKeyException.DOES_NOT_EXIST)) request, ConfirmationKeyException(ConfirmationKeyException.DOES_NOT_EXIST))
try: try:
get_object_from_key(confirmation_key, confirmation.type) get_object_from_key(confirmation_key, confirmation.type, activate_object=False)
except ConfirmationKeyException as exception: except ConfirmationKeyException as exception:
return render_confirmation_key_error(request, exception) return render_confirmation_key_error(request, exception)
@ -92,7 +92,6 @@ def accounts_register(request: HttpRequest) -> HttpResponse:
return render_confirmation_key_error( return render_confirmation_key_error(
request, ConfirmationKeyException(ConfirmationKeyException.DOES_NOT_EXIST)) request, ConfirmationKeyException(ConfirmationKeyException.DOES_NOT_EXIST))
realm = prereg_user.realm realm = prereg_user.realm
try: try:
email_allowed_for_realm(email, realm) email_allowed_for_realm(email, realm)
except DomainNotAllowedForRealmError: except DomainNotAllowedForRealmError: