diff --git a/confirmation/models.py b/confirmation/models.py index 0f966ea03e..165e09b9da 100644 --- a/confirmation/models.py +++ b/confirmation/models.py @@ -18,7 +18,7 @@ from django.utils.timezone import now as timezone_now from zerver.lib.send_email import send_email from zerver.lib.utils import generate_random_token -from zerver.models import PreregistrationUser, EmailChangeStatus, MultiuseInvite +from zerver.models import PreregistrationUser, EmailChangeStatus, MultiuseInvite, UserProfile from random import SystemRandom import string from typing import Any, Dict, Optional, Text, Union @@ -48,7 +48,7 @@ def generate_key(): return ''.join(generator.choice(string.ascii_lowercase + string.digits) for _ in range(24)) def get_object_from_key(confirmation_key, confirmation_type): - # type: (str, int) -> Union[MultiuseInvite, PreregistrationUser, EmailChangeStatus] + # type: (str, int) -> Union[MultiuseInvite, PreregistrationUser, EmailChangeStatus, UserProfile] # Confirmation keys used to be 40 characters if len(confirmation_key) not in (24, 40): raise ConfirmationKeyException(ConfirmationKeyException.WRONG_LENGTH) diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index 8555fa6baa..a892ca5e7e 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -863,9 +863,9 @@ so we didn't send them an invitation. We did send invitations to everyone else!" # type: () -> None user = self.example_user('hamlet') registration_key = create_confirmation_link(user, 'host', Confirmation.USER_REGISTRATION).split('/')[-1] - with self.assertRaises(ConfirmationKeyException) as exception: + with self.assertRaises(ConfirmationKeyException) as cm: get_object_from_key(registration_key, Confirmation.INVITATION) - self.assertEqual(exception.error_type, ConfirmationKeyException.DOES_NOT_EXIST) + self.assertEqual(cm.exception.error_type, ConfirmationKeyException.DOES_NOT_EXIST) class InvitationsTestCase(InviteUserBase): def test_successful_get_open_invitations(self): @@ -1107,9 +1107,10 @@ class EmailUnsubscribeTests(ZulipTestCase): def test_error_unsubscribe(self): # type: () -> None - # An invalid insubscribe token "test123" produces an error. + # An invalid insubscribe token "test123" produces an error, in this + # case, a link malformed error. result = self.client_get('/accounts/unsubscribe/missed_messages/test123') - self.assert_in_response('Unknown email unsubscribe request', result) + self.assert_in_response('Make sure you copied the link', result) # An unknown message type "fake" produces an error. user_profile = self.example_user('hamlet') diff --git a/zerver/views/unsubscribe.py b/zerver/views/unsubscribe.py index c6050ec6fa..450964a2b5 100644 --- a/zerver/views/unsubscribe.py +++ b/zerver/views/unsubscribe.py @@ -4,19 +4,19 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render from typing import Callable -from confirmation.models import Confirmation +from confirmation.models import Confirmation, get_object_from_key, \ + render_confirmation_key_error, ConfirmationKeyException from zerver.lib.actions import do_change_notification_settings, clear_scheduled_emails from zerver.models import UserProfile, ScheduledEmail from zerver.context_processors import common_context -def process_unsubscribe(request: HttpRequest, token: str, subscription_type: str, +def process_unsubscribe(request: HttpRequest, confirmation_key: str, subscription_type: str, unsubscribe_function: Callable[[UserProfile], None]) -> HttpResponse: try: - confirmation = Confirmation.objects.get(confirmation_key=token) - except Confirmation.DoesNotExist: - return render(request, 'zerver/unsubscribe_link_error.html') + user_profile = get_object_from_key(confirmation_key, Confirmation.UNSUBSCRIBE) + except ConfirmationKeyException as exception: + return render_confirmation_key_error(request, exception) - user_profile = confirmation.content_object unsubscribe_function(user_profile) context = common_context(user_profile) context.update({"subscription_type": subscription_type})