Changeset 76ebb1b in OpenWorkouts-current
- Timestamp:
- Feb 18, 2019, 12:54:45 PM (5 years ago)
- Branches:
- current, feature/docs, master
- Children:
- 4af38e8
- Parents:
- d6da99e
- Files:
-
- 5 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
development.ini
rd6da99e r76ebb1b 30 30 {BT]KrSx`b3pmRj<Z&e3QP|fgPGEZT@\# 31 31 auth.secret = l9|^@~wQoVKPQoI`GHK5M9ps@S7L:QNU?pF}.jI(9RWZVc<EM)aQv/j~l\#xC++;5 32 33 # pyramid_mailer configuration 34 mail.default_sender = noreply@openworkouts.org 35 mail.queue_path = %(here)s/var/spool/mqueue 36 mail.queue_processor_lock = %(here)s/var/run/mail-queue-processor.lock 37 mail.host = mail.openworkouts.org 38 mail.tls = True 39 mail.username = noreply@openworkouts.org 40 mail.password = PASSWORD 32 41 33 42 -
ow/__init__.py
rd6da99e r76ebb1b 37 37 config.include('pyramid_retry') 38 38 config.include('pyramid_zodbconn') 39 config.include('pyramid_mailer') 39 40 config.add_static_view('static', 'static', cache_max_age=3600) 40 41 config.add_translation_dirs( -
ow/models/user.py
rd6da99e r76ebb1b 39 39 self.__password = None 40 40 self.last_workout_id = 0 41 # has this user verified his account? 42 self.verified = False 43 self.verification_token = None 41 44 super(User, self).__init__() 42 45 -
ow/tests/views/test_user.py
rd6da99e r76ebb1b 6 6 from unittest.mock import Mock, patch 7 7 from io import BytesIO 8 from uuid import UUID 8 9 9 10 import pytest … … 112 113 }) 113 114 return request 115 116 @patch('ow.views.user.remember') 117 def test_verify_already_verified(self, remember, dummy_request, john): 118 john.verified = True 119 response = user_views.verify(john, dummy_request) 120 assert isinstance(response, HTTPFound) 121 assert response.location == dummy_request.resource_url(john) 122 # user was not authenticated 123 assert not remember.called 124 # verified status did not change 125 assert john.verified 126 127 @patch('ow.views.user.remember') 128 def test_verify_no_subpath(self, remember, dummy_request, john): 129 response = user_views.verify(john, dummy_request) 130 # the verify info page is rendered, we don't pass anything to the 131 # rendering context 132 assert response == {} 133 # user was not authenticated 134 assert not remember.called 135 # verified status did not change 136 assert not john.verified 137 138 def test_verify_subpath_not_verified(self, dummy_request, john): 139 dummy_request.subpath = ['not_the_token'] 140 response = user_views.verify(john, dummy_request) 141 # the verify info page is rendered, we don't pass anything to the 142 # rendering context 143 assert response == {} 144 145 @patch('ow.views.user.remember') 146 def test_verify_wrong_token(self, remember, dummy_request, john): 147 token = 'some-uuid4' 148 john.verification_token = 'some-other-uuid4' 149 dummy_request.subpath = [token] 150 response = user_views.verify(john, dummy_request) 151 # the verify info page is rendered, we don't pass anything to the 152 # rendering context 153 assert response == {} 154 # user was not authenticated 155 assert not remember.called 156 # verified status did not change, neither did the token 157 assert not john.verified 158 assert john.verification_token == 'some-other-uuid4' 159 160 @patch('ow.views.user.remember') 161 def test_verify_verifying(self, remember, dummy_request, john): 162 token = 'some-uuid4' 163 john.verification_token = token 164 dummy_request.subpath = [token] 165 response = user_views.verify(john, dummy_request) 166 # redirect to user page 167 assert isinstance(response, HTTPFound) 168 assert response.location == dummy_request.resource_url(john) 169 # user was authenticated after verified 170 remember.assert_called_with(dummy_request, str(john.uid)) 171 # user has been verified 172 assert john.verified 114 173 115 174 def test_dashboard_redirect_unauthenticated(self, root): … … 369 428 request.POST['email'] = 'john.doe@example.net' 370 429 request.POST['password'] = 'badpassword' 430 # verify the user first 431 request.root.users[0].verified = True 371 432 response = user_views.login(request.root, request) 372 433 assert response['message'] == u'Wrong password' 373 434 374 435 @patch('ow.views.user.remember') 375 def test_login_post_ ok(self, rem, dummy_request, john):436 def test_login_post_unverified(self, rem, dummy_request, john): 376 437 request = dummy_request 377 438 request.method = 'POST' … … 379 440 request.POST['email'] = 'john.doe@example.net' 380 441 request.POST['password'] = 's3cr3t' 442 response = user_views.login(request.root, request) 443 assert response['message'] == u'You have to verify your account first' 444 445 @patch('ow.views.user.remember') 446 def test_login_post_ok(self, rem, dummy_request, john): 447 request = dummy_request 448 request.method = 'POST' 449 request.POST['submit'] = True 450 request.POST['email'] = 'john.doe@example.net' 451 request.POST['password'] = 's3cr3t' 452 # verify the user first 453 john.verified = True 381 454 response = user_views.login(request.root, request) 382 455 assert isinstance(response, HTTPFound) … … 620 693 assert response['form'].errorlist() == '' 621 694 622 def test_signup_post_ok(self, signup_post_request): 695 @patch('ow.views.user.send_verification_email') 696 def test_signup_post_ok(self, sve, signup_post_request): 623 697 request = signup_post_request 624 698 assert 'jack.black@example.net' not in request.root.emails … … 629 703 assert 'jack.black@example.net' in request.root.emails 630 704 assert 'JackBlack' in request.root.all_nicknames 705 # user is in "unverified" state 706 user = request.root.get_user_by_email('jack.black@example.net') 707 assert not user.verified 708 assert isinstance(user.verification_token, UUID) 709 # also, we sent an email to that user 710 sve.assert_called_once_with(request, user) 631 711 632 712 def test_signup_missing_required(self, signup_post_request): -
ow/utilities.py
rd6da99e r76ebb1b 8 8 from decimal import Decimal 9 9 from shutil import copyfileobj 10 from uuid import uuid4 10 11 11 12 from unidecode import unidecode … … 20 21 21 22 log = logging.getLogger(__name__) 23 24 25 def get_verification_token(): 26 """ 27 Generate a new uuid4 verification token we can give a user for 28 verification purposes. 29 uuid4 is a standard that generates a randomly generated token, 30 optimized for a very low chance of collisions. But even if 31 we had a collision, it wouldn't matter - it's simple some users 32 getting the same token in their verification mail. 33 """ 34 return uuid4() 22 35 23 36 -
ow/views/user.py
rd6da99e r76ebb1b 22 22 from ..models.root import OpenWorkouts 23 23 from ..views.renderers import OWFormRenderer 24 from ..utilities import timedelta_to_hms 24 from ..utilities import timedelta_to_hms, get_verification_token 25 from ..mail import send_verification_email 25 26 26 27 _ = TranslationStringFactory('OpenWorkouts') … … 59 60 user = context.get_user_by_email(email) 60 61 if user: 61 password = request.POST.get('password', None) 62 if password is not None and user.check_password(password): 63 headers = remember(request, str(user.uid)) 64 redirect_url = return_to or request.resource_url(user) 65 return HTTPFound(location=redirect_url, headers=headers) 62 if user.verified: 63 password = request.POST.get('password', None) 64 if password is not None and user.check_password(password): 65 headers = remember(request, str(user.uid)) 66 redirect_url = return_to or request.resource_url(user) 67 return HTTPFound(location=redirect_url, headers=headers) 68 else: 69 message = _('Wrong password') 66 70 else: 67 message = _(' Wrong password')71 message = _('You have to verify your account first') 68 72 else: 69 73 message = _('Wrong email address') … … 94 98 if 'submit' in request.POST and form.validate(): 95 99 user = form.bind(User(), exclude=['password_confirm']) 100 user.verified = False 101 user.verification_token = get_verification_token() 96 102 context.add_user(user) 103 # send a verification link to the user email address 104 send_verification_email(request, user) 97 105 # Send to login 98 106 return HTTPFound(location=request.resource_url(context)) … … 101 109 'form': OWFormRenderer(form) 102 110 } 111 112 113 @view_config( 114 context=User, 115 name="verify", 116 renderer='ow:templates/verify.pt') 117 def verify(context, request): 118 redirect_url = request.resource_url(context) 119 120 # user has been verified already, send to dashboard 121 if getattr(context, 'verified', False): 122 return HTTPFound(location=redirect_url) 123 124 # Look for a verification token, then check if we can verify the user with 125 # that token 126 verified = len(request.subpath) > 0 127 token = getattr(context, 'verification_token', False) 128 verified = verified and token and str(token) == request.subpath[0] 129 if verified: 130 # verified, log in automatically and send to the dashboard 131 context.verified = True 132 headers = remember(request, str(context.uid)) 133 return HTTPFound(location=redirect_url, headers=headers) 134 135 # if we can not verify the user, show a page with some info about it 136 return {} 103 137 104 138 -
setup.py
rd6da99e r76ebb1b 17 17 'pyramid_tm', 18 18 'pyramid_zodbconn', 19 'pyramid_simpleform==0.7dev0', # version needed for python3 20 'pyramid_mailer', 19 21 'transaction', 20 22 'ZODB3', … … 25 27 'bcrypt', 26 28 'FormEncode', 27 'pyramid_simpleform==0.7dev0', # version needed for python328 29 'unidecode', 29 30 'gpxpy',
Note: See TracChangeset
for help on using the changeset viewer.