Changeset 8bae554 in OpenWorkouts-current


Ignore:
Timestamp:
Feb 21, 2019, 9:54:45 PM (4 years ago)
Author:
Borja Lopez <borja@…>
Branches:
current, feature/docs, master
Children:
d411dae
Parents:
38171c6
Message:

(#67) Allow users to send again the verification link (up to 3 times)
to the email address they provided when signing up.

Location:
ow
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • ow/models/user.py

    r38171c6 r8bae554  
    4242        self.verified = False
    4343        self.verification_token = None
     44        self.verification_tokens_sent = 0
    4445        super(User, self).__init__()
    4546
  • ow/templates/login.pt

    r38171c6 r8bae554  
    2020
    2121          <div id="messages" class="message message-error"
    22                tal:content="message" tal:condition="message != ''"></div>
     22               tal:condition="message != ''">
     23            <tal:message tal:content="message"></tal:message>
     24            <tal:resend-verify tal:condition="resend_verify_link is not None">
     25              <br>
     26              <a href="" tal:attributes="href resend_verify_link"
     27                 i18n:translate="">Please send me the verification link again</a>
     28            </tal:resend-verify>
     29          </div>
    2330
    2431          <fieldset>
  • ow/tests/views/test_user.py

    r38171c6 r8bae554  
    172172        assert john.verified
    173173
     174    @patch('ow.views.user.send_verification_email')
     175    def test_resend_verification_already_verified(
     176            self, sve, dummy_request, john):
     177        john.verified = True
     178        assert john.verification_token is None
     179        response = user_views.resend_verification_link(john, dummy_request)
     180        assert isinstance(response, HTTPFound)
     181        assert response.location == dummy_request.resource_url(
     182            dummy_request.root, 'login', query={'message': 'already-verified'}
     183        )
     184        # no emails have been sent
     185        assert not sve.called
     186        # the token has not been modified
     187        assert john.verification_token is None
     188
     189    @patch('ow.views.user.send_verification_email')
     190    def test_resend_verification(self, sve, dummy_request, john):
     191        john.verified = False
     192        john.verification_token = 'faked-uuid4-verification-token'
     193        assert john.verification_tokens_sent == 0
     194        response = user_views.resend_verification_link(john, dummy_request)
     195        assert isinstance(response, HTTPFound)
     196        assert response.location == dummy_request.resource_url(
     197            dummy_request.root, 'login',
     198            query={'message': 'link-sent', 'email': john.email}
     199        )
     200        # no emails have been sent
     201        sve.assert_called_once_with(dummy_request, john)
     202        # the token has not been modified
     203        assert john.verification_token == 'faked-uuid4-verification-token'
     204        # and we have registered that we sent a token
     205        assert john.verification_tokens_sent == 1
     206
     207    @patch('ow.views.user.send_verification_email')
     208    def test_resend_verification_new_token(self, sve, dummy_request, john):
     209        john.verified = False
     210        john.verification_token = None
     211        assert john.verification_tokens_sent == 0
     212        response = user_views.resend_verification_link(john, dummy_request)
     213        assert isinstance(response, HTTPFound)
     214        assert response.location == dummy_request.resource_url(
     215            dummy_request.root, 'login',
     216            query={'message': 'link-sent', 'email': john.email}
     217        )
     218        # no emails have been sent
     219        sve.assert_called_once_with(dummy_request, john)
     220        # the token has been modified
     221        assert john.verification_token is not None
     222        assert john.verification_tokens_sent == 1
     223
     224    @patch('ow.views.user.send_verification_email')
     225    def test_resend_verification_limit(
     226            self, sve, dummy_request, john):
     227        john.verified = False
     228        john.verification_token = 'faked-uuid4-verification-token'
     229        john.verification_tokens_sent = 4
     230        response = user_views.resend_verification_link(john, dummy_request)
     231        assert isinstance(response, HTTPFound)
     232        assert response.location == dummy_request.resource_url(
     233            dummy_request.root, 'login',
     234            query={'message': 'max-tokens-sent', 'email': john.email}
     235        )
     236        # no emails have been sent
     237        assert not sve.called
     238        # the token has not been modified
     239        assert john.verification_token == 'faked-uuid4-verification-token'
     240        assert john.verification_tokens_sent == 4
     241
    174242    def test_dashboard_redirect_unauthenticated(self, root):
    175243        """
    176         Anoymous access to the root object, send the user to the login page.
     244        Anonymous access to the root object, send the user to the login page.
    177245
    178246        Instead of reusing the DummyRequest from the request fixture, we do
     
    400468        assert response['password'] == ''
    401469        assert response['redirect_url'] == request.resource_url(request.root)
     470        assert response['resend_verify_link'] is None
    402471
    403472    def test_login_get_return_to(self, dummy_request, john):
     
    413482        response = user_views.login(request.root, request)
    414483        assert response['redirect_url'] == workout_url
     484
     485    def test_login_get_GET_messages(self, dummy_request):
     486        """
     487        GET request to access the login page, passing as a GET parameter
     488        a "message key" so a given message is shown to the user
     489        """
     490        request = dummy_request
     491        # first try with the keys we know there are messages associated to
     492        request.GET['message'] = 'already-verified'
     493        response = user_views.login(request.root, request)
     494        assert response['message'] == 'User has been verified already'
     495        request.GET['message'] = 'link-sent'
     496        response = user_views.login(request.root, request)
     497        assert response['message'] == (
     498            'Verification link sent, please check your inbox')
     499        request.GET['message'] = 'max-tokens-sent'
     500        response = user_views.login(request.root, request)
     501        assert response['message'] == (
     502            'We already sent you the verification link more than three times')
     503
     504        # now try with a key that has no message assigned
     505        request.GET['message'] = 'invalid-message-key'
     506        response = user_views.login(request.root, request)
     507        assert response['message'] == ''
     508
     509    def test_login_get_GET_email(self, dummy_request):
     510        """
     511        GET request to access the login page, passing as a GET parameter
     512        an email address. That email is used to automatically fill in the
     513        email input in the login form.
     514        """
     515        request = dummy_request
     516        # first try with the keys we know there are messages associated to
     517        request.GET['email'] = 'user@example.net'
     518        response = user_views.login(request.root, request)
     519        assert response['email'] == 'user@example.net'
    415520
    416521    def test_login_post_wrong_email(self, dummy_request):
  • ow/views/user.py

    r38171c6 r8bae554  
    5050    renderer='ow:templates/login.pt')
    5151def login(context, request):
    52     message = ''
    53     email = ''
     52    # messages is a dict of pre-defined messages we would need to show to the
     53    # user when coming back to the login page after certain actions
     54    messages = {
     55        'already-verified': _('User has been verified already'),
     56        'link-sent': _('Verification link sent, please check your inbox'),
     57        'max-tokens-sent': _(
     58            'We already sent you the verification link more than three times')
     59    }
     60    message = request.GET.get('message', '')
     61    if message:
     62        message = messages.get(message, '')
     63    email = request.GET.get('email', '')
    5464    password = ''
    5565    return_to = request.params.get('return_to')
    5666    redirect_url = return_to or request.resource_url(request.root)
     67    # If the user still has to verify the account, this will be set to the
     68    # proper link to re-send the verification email
     69    resend_verify_link = None
    5770
    5871    if 'submit' in request.POST:
     
    7083            else:
    7184                message = _('You have to verify your account first')
     85                resend_verify_link = request.resource_url(
     86                    user, 'resend-verification-link'
     87                )
    7288        else:
    7389            message = _('Wrong email address')
     
    7793        'email': email,
    7894        'password': password,
    79         'redirect_url': redirect_url
     95        'redirect_url': redirect_url,
     96        'resend_verify_link': resend_verify_link
    8097    }
    8198
     
    103120        # send a verification link to the user email address
    104121        send_verification_email(request, user)
     122        user.verification_tokens_sent += 1
    105123        # Send to login
    106124        return HTTPFound(location=request.resource_url(context))
     
    135153    # if we can not verify the user, show a page with some info about it
    136154    return {}
     155
     156
     157@view_config(
     158    context=User,
     159    name="resend-verification-link")
     160def resend_verification_link(context, request):
     161    """
     162    Send an email with the verification link, only if the user has not
     163    been verified yet
     164    """
     165    # the message to be shown when the user gets back to the login page
     166    query = {'message': 'already-verified'}
     167    if not context.verified:
     168        tokens_sent = getattr(context, 'verification_tokens_sent', 0)
     169        if tokens_sent > 3:
     170            # we already sent the token 3 times, we don't send it anymore
     171            query = {'message': 'max-tokens-sent', 'email': context.email}
     172        else:
     173            if context.verification_token is None:
     174                # for some reason the verification token is not there, get one
     175                context.verification_token = get_verification_token()
     176            send_verification_email(request, context)
     177            context.verification_tokens_sent = tokens_sent + 1
     178            query = {'message': 'link-sent', 'email': context.email}
     179    # Send to login
     180    url = request.resource_url(request.root, 'login', query=query)
     181    return HTTPFound(location=url)
    137182
    138183
Note: See TracChangeset for help on using the changeset viewer.