pyramid-fullauth 0.3.0__py2.7.egg

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. EGG-INFO/PKG-INFO +176 -0
  2. EGG-INFO/SOURCES.txt +91 -0
  3. EGG-INFO/dependency_links.txt +1 -0
  4. EGG-INFO/not-zip-safe +1 -0
  5. EGG-INFO/requires.txt +17 -0
  6. EGG-INFO/top_level.txt +2 -0
  7. pyramid_fullauth/__init__.py +105 -0
  8. pyramid_fullauth/__init__.pyc +0 -0
  9. pyramid_fullauth/auth.py +66 -0
  10. pyramid_fullauth/auth.pyc +0 -0
  11. pyramid_fullauth/events.py +267 -0
  12. pyramid_fullauth/events.pyc +0 -0
  13. pyramid_fullauth/exceptions.py +47 -0
  14. pyramid_fullauth/exceptions.pyc +0 -0
  15. pyramid_fullauth/models/__init__.py +189 -0
  16. pyramid_fullauth/models/__init__.pyc +0 -0
  17. pyramid_fullauth/models/mixins/__init__.py +9 -0
  18. pyramid_fullauth/models/mixins/__init__.pyc +0 -0
  19. pyramid_fullauth/models/mixins/email.py +81 -0
  20. pyramid_fullauth/models/mixins/email.pyc +0 -0
  21. pyramid_fullauth/models/mixins/password.py +141 -0
  22. pyramid_fullauth/models/mixins/password.pyc +0 -0
  23. pyramid_fullauth/request.py +69 -0
  24. pyramid_fullauth/request.pyc +0 -0
  25. pyramid_fullauth/resources/helpers/social.mako +17 -0
  26. pyramid_fullauth/resources/locale/pyramid_fullauth.pot +216 -0
  27. pyramid_fullauth/resources/templates/403.mako +11 -0
  28. pyramid_fullauth/resources/templates/_form.login.mako +44 -0
  29. pyramid_fullauth/resources/templates/_form.register.mako +47 -0
  30. pyramid_fullauth/resources/templates/_social.login.mako +17 -0
  31. pyramid_fullauth/resources/templates/activate.mako +14 -0
  32. pyramid_fullauth/resources/templates/email_change.mako +33 -0
  33. pyramid_fullauth/resources/templates/layout.mako +13 -0
  34. pyramid_fullauth/resources/templates/login.mako +14 -0
  35. pyramid_fullauth/resources/templates/register.mako +22 -0
  36. pyramid_fullauth/resources/templates/reset.mako +34 -0
  37. pyramid_fullauth/resources/templates/reset.proceed.mako +41 -0
  38. pyramid_fullauth/routing/__init__.py +5 -0
  39. pyramid_fullauth/routing/__init__.pyc +0 -0
  40. pyramid_fullauth/routing/predicates.py +86 -0
  41. pyramid_fullauth/routing/predicates.pyc +0 -0
  42. pyramid_fullauth/tools.py +66 -0
  43. pyramid_fullauth/tools.pyc +0 -0
  44. pyramid_fullauth/views/__init__.py +15 -0
  45. pyramid_fullauth/views/__init__.pyc +0 -0
  46. pyramid_fullauth/views/basic/__init__.py +5 -0
  47. pyramid_fullauth/views/basic/__init__.pyc +0 -0
  48. pyramid_fullauth/views/basic/activate.py +44 -0
  49. pyramid_fullauth/views/basic/activate.pyc +0 -0
  50. pyramid_fullauth/views/basic/forbidden.py +47 -0
  51. pyramid_fullauth/views/basic/forbidden.pyc +0 -0
  52. pyramid_fullauth/views/basic/login.py +128 -0
  53. pyramid_fullauth/views/basic/login.pyc +0 -0
  54. pyramid_fullauth/views/basic/logout.py +28 -0
  55. pyramid_fullauth/views/basic/logout.pyc +0 -0
  56. pyramid_fullauth/views/basic/profile/__init__.py +5 -0
  57. pyramid_fullauth/views/basic/profile/__init__.pyc +0 -0
  58. pyramid_fullauth/views/basic/profile/email.py +107 -0
  59. pyramid_fullauth/views/basic/profile/email.pyc +0 -0
  60. pyramid_fullauth/views/basic/profile/password.py +128 -0
  61. pyramid_fullauth/views/basic/profile/password.pyc +0 -0
  62. pyramid_fullauth/views/basic/register.py +110 -0
  63. pyramid_fullauth/views/basic/register.pyc +0 -0
  64. pyramid_fullauth/views/social.py +218 -0
  65. pyramid_fullauth/views/social.pyc +0 -0
  66. tests/__init__.py +1 -0
  67. tests/__init__.pyc +0 -0
  68. tests/conftest.py +190 -0
  69. tests/conftest.pyc +0 -0
  70. tests/tools.py +54 -0
  71. tests/tools.pyc +0 -0
  72. tests/unit/test_default_settings.py +15 -0
  73. tests/unit/test_default_settings.pyc +0 -0
  74. tests/unit/test_groupfinder.py +20 -0
  75. tests/unit/test_groupfinder.pyc +0 -0
  76. tests/unit/test_social_view.py +65 -0
  77. tests/unit/test_social_view.pyc +0 -0
  78. tests/unit/test_tools.py +24 -0
  79. tests/unit/test_tools.pyc +0 -0
  80. tests/unit/test_user_active.py +31 -0
  81. tests/unit/test_user_active.pyc +0 -0
  82. tests/unit/test_user_admin.py +61 -0
  83. tests/unit/test_user_admin.pyc +0 -0
  84. tests/unit/test_user_email.py +37 -0
  85. tests/unit/test_user_email.pyc +0 -0
  86. tests/unit/test_user_password.py +52 -0
  87. tests/unit/test_user_password.pyc +0 -0
  88. tests/unit/test_user_providers.py +24 -0
  89. tests/unit/test_user_providers.pyc +0 -0
  90. tests/unit/test_user_repr.py +29 -0
  91. tests/unit/test_user_repr.pyc +0 -0
  92. tests/unit/test_validators.py +44 -0
  93. tests/unit/test_validators.pyc +0 -0
  94. tests/views/__init__.py +1 -0
  95. tests/views/__init__.pyc +0 -0
  96. tests/views/conftest.py +15 -0
  97. tests/views/conftest.pyc +0 -0
  98. tests/views/test_activation.py +83 -0
  99. tests/views/test_activation.pyc +0 -0
  100. tests/views/test_email.py +175 -0
  101. tests/views/test_email.pyc +0 -0
  102. tests/views/test_events.py +546 -0
  103. tests/views/test_events.pyc +0 -0
  104. tests/views/test_login.py +151 -0
  105. tests/views/test_login.pyc +0 -0
  106. tests/views/test_login_social.py +254 -0
  107. tests/views/test_login_social.pyc +0 -0
  108. tests/views/test_logout.py +42 -0
  109. tests/views/test_logout.pyc +0 -0
  110. tests/views/test_register.py +134 -0
  111. tests/views/test_register.pyc +0 -0
  112. tests/views/test_reset.py +100 -0
  113. tests/views/test_reset.pyc +0 -0
@@ -0,0 +1,128 @@
1
+ # Copyright (c) 2013 - 2014 by pyramid_fullauth authors and contributors <see AUTHORS file>
2
+ #
3
+ # This module is part of pyramid_fullauth and is released under
4
+ # the MIT License (MIT): http://opensource.org/licenses/MIT
5
+ """Profile related views."""
6
+
7
+ from pyramid.view import view_config, view_defaults
8
+ from pyramid.httpexceptions import HTTPFound
9
+ from pyramid.security import NO_PERMISSION_REQUIRED
10
+
11
+ from sqlalchemy.orm.exc import NoResultFound
12
+ import pyramid_basemodel
13
+
14
+ from pyramid_fullauth.views import BaseView
15
+ from pyramid_fullauth.models import User, AuthenticationProvider
16
+
17
+ from pyramid_fullauth.events import BeforeReset
18
+ from pyramid_fullauth.events import AfterResetRequest
19
+ from pyramid_fullauth.events import AfterReset
20
+ from pyramid_fullauth.exceptions import ValidateError
21
+ from pyramid_fullauth.tools import validate_passsword
22
+
23
+
24
+ @view_defaults(route_name='password:reset', permission=NO_PERMISSION_REQUIRED,
25
+ renderer='pyramid_fullauth:resources/templates/reset.mako')
26
+ class PasswordResetView(BaseView):
27
+
28
+ """Profile related views."""
29
+
30
+ @view_config()
31
+ def get(self):
32
+ """Password reset request view."""
33
+ csrf_token = self.request.session.get_csrf_token()
34
+
35
+ return {'status': True, 'csrf_token': csrf_token}
36
+
37
+ @view_config(request_method='POST', check_csrf=True)
38
+ def post(self):
39
+ """View processing requests to reset password."""
40
+ csrf_token = self.request.session.get_csrf_token()
41
+
42
+ try:
43
+ user = pyramid_basemodel.Session.query(User).filter(
44
+ User.email == self.request.POST.get('email', '')).one()
45
+ except NoResultFound:
46
+ return {'status': False,
47
+ 'msg': self.request._('user-not-exists',
48
+ default='User does not exists',
49
+ domain='pyramid_fullauth'),
50
+ 'csrf_token': csrf_token}
51
+
52
+ user.set_reset()
53
+ try:
54
+ self.request.registry.notify(AfterResetRequest(self.request, user))
55
+ except HTTPFound as redirect:
56
+ return redirect
57
+
58
+ return HTTPFound(location='/')
59
+
60
+
61
+ @view_defaults(route_name='password:reset:continue', permission=NO_PERMISSION_REQUIRED,
62
+ renderer='pyramid_fullauth:resources/templates/reset.proceed.mako')
63
+ class PasswordResetContinueView(BaseView):
64
+
65
+ """
66
+ Password reset views.
67
+
68
+ These views display actual reset password views.
69
+ """
70
+
71
+ @view_config(request_method='GET')
72
+ def get(self):
73
+ """Display actual password reset form."""
74
+ self.request.logout()
75
+ return {
76
+ 'status': True,
77
+ 'csrf_token': self.request.session.get_csrf_token()
78
+ }
79
+
80
+ @view_config(request_method='POST', check_csrf=True)
81
+ def post(self):
82
+ """Validate and possibly accept new email."""
83
+ user = self.request.matchdict.get('user')
84
+
85
+ password = self.request.POST.get('password', None)
86
+ password_confirm = self.request.POST.get('confirm_password', None)
87
+ if password == password_confirm:
88
+
89
+ try:
90
+ self.request.registry.notify(BeforeReset(self.request, user))
91
+ validate_passsword(self.request, password, user)
92
+
93
+ user.reset_key = None
94
+ try:
95
+ pyramid_basemodel.Session.query(AuthenticationProvider).filter(
96
+ AuthenticationProvider.user_id == user.id,
97
+ AuthenticationProvider.provider == u'email'
98
+ ).one()
99
+ except NoResultFound:
100
+ user.providers.append(
101
+ AuthenticationProvider(
102
+ provider=u'email',
103
+ provider_id=user.id
104
+ )
105
+ )
106
+
107
+ pyramid_basemodel.Session.flush()
108
+ except (ValidateError, AttributeError) as e:
109
+ return {
110
+ 'status': False,
111
+ 'msg': str(e),
112
+ 'csrf_token': self.request.session.get_csrf_token()
113
+ }
114
+
115
+ try:
116
+ self.request.registry.notify(AfterReset(self.request, user))
117
+ except HTTPFound as redirect:
118
+ return redirect
119
+ else:
120
+ return {
121
+ 'status': False,
122
+ 'msg': self.request._('password-mismatch',
123
+ default='Password doesn\'t match',
124
+ domain='pyramid_fullauth'),
125
+ 'csrf_token': self.request.session.get_csrf_token()
126
+ }
127
+
128
+ return self.get()
@@ -0,0 +1,110 @@
1
+ # Copyright (c) 2013 - 2014 by pyramid_fullauth authors and contributors <see AUTHORS file>
2
+ #
3
+ # This module is part of pyramid_fullauth and is released under
4
+ # the MIT License (MIT): http://opensource.org/licenses/MIT
5
+ """Registration related views."""
6
+
7
+ from pyramid.view import view_config, view_defaults
8
+ from pyramid.httpexceptions import HTTPFound
9
+ from pyramid.security import NO_PERMISSION_REQUIRED
10
+
11
+ import pyramid_basemodel
12
+
13
+ from pyramid_fullauth.views import BaseView
14
+ from pyramid_fullauth.models import User, AuthenticationProvider
15
+ from pyramid_fullauth.events import BeforeRegister, AfterRegister
16
+ from pyramid_fullauth import tools
17
+ from pyramid_fullauth.exceptions import ValidateError
18
+
19
+
20
+ @view_defaults(route_name='register', permission=NO_PERMISSION_REQUIRED,
21
+ renderer="pyramid_fullauth:resources/templates/register.mako")
22
+ class RegisterView(BaseView):
23
+
24
+ """Registration views."""
25
+
26
+ @view_config(request_method='GET')
27
+ def get(self):
28
+ """Display registration form."""
29
+ csrf_token = self.request.session.get_csrf_token()
30
+ return {'status': True, 'msg': None, 'csrf_token': csrf_token, 'errors': {}}
31
+
32
+ @view_config(request_method='POST', check_csrf=True)
33
+ @view_config(request_method='POST', check_csrf=True, xhr=True, renderer="json")
34
+ def post(self):
35
+ """Process registration request."""
36
+ response = {
37
+ 'status': False,
38
+ 'msg': self.request._('You have an error in your registration form',
39
+ domain='pyramid_fullauth'),
40
+ 'csrf_token': self.request.session.get_csrf_token(),
41
+ 'errors': {},
42
+ }
43
+
44
+ user = User()
45
+ user.address_ip = self.request.remote_addr
46
+
47
+ response = self._fillin_user(response, user)
48
+
49
+ if not response['errors']:
50
+ response['status'] = True
51
+ response['msg'] = self.request._(
52
+ 'You have successfully registered', domain='pyramid_fullauth')
53
+
54
+ try:
55
+ self.request.registry.notify(AfterRegister(self.request, user, response))
56
+ except HTTPFound as redirect:
57
+ return redirect
58
+
59
+ return response
60
+
61
+ def _fillin_user(self, response, user):
62
+ """
63
+ Fill new user object in, with sent data.
64
+
65
+ :param dict response: response to return from register view
66
+ :param pyramid_fullauth.models.User user: new user object
67
+
68
+ :returns: response
69
+ :rtype: dict
70
+ """
71
+ email = self.request.POST.get('email', u'')
72
+ # here if e-mail is already in database
73
+
74
+ if pyramid_basemodel.Session.query(User).filter(User.email == email).count() != 0:
75
+ response['errors']['email'] = self.request._(
76
+ 'User with given e-mail already exists!',
77
+ domain='pyramid_fullauth')
78
+ try:
79
+ try:
80
+ user.email = email
81
+ except ValidateError as e:
82
+ # do not overwrite existing error
83
+ if 'email' not in response['errors']:
84
+ response['errors']['email'] = str(e)
85
+
86
+ if self.config.register.password.require:
87
+ try:
88
+ tools.validate_passsword(self.request,
89
+ self.request.POST.get('password', u''),
90
+ user)
91
+ except ValidateError as e:
92
+ response['errors']['password'] = e.message
93
+ else:
94
+ user.password = tools.password_generator(
95
+ self.config.register.password.length_min)
96
+
97
+ self.request.registry.notify(BeforeRegister(self.request, user, response['errors']))
98
+ if not response['errors']:
99
+ pyramid_basemodel.Session.add(user)
100
+ pyramid_basemodel.Session.flush()
101
+
102
+ # lets add AuthenticationProvider as email!
103
+ user.providers.append(
104
+ AuthenticationProvider(provider=u'email', provider_id=user.id))
105
+ else:
106
+ return response
107
+ except AttributeError as e:
108
+ response['errors']['msg'] = str(e)
109
+
110
+ return response
@@ -0,0 +1,218 @@
1
+ # Copyright (c) 2013 - 2014 by pyramid_fullauth authors and contributors <see AUTHORS file>
2
+ #
3
+ # This module is part of pyramid_fullauth and is released under
4
+ # the MIT License (MIT): http://opensource.org/licenses/MIT
5
+ """Social login/registration view."""
6
+ import logging
7
+
8
+ from pyramid.view import view_config
9
+ from pyramid.httpexceptions import HTTPFound
10
+ from pyramid.security import NO_PERMISSION_REQUIRED
11
+
12
+ from sqlalchemy.orm.exc import NoResultFound
13
+ from sqlalchemy.exc import IntegrityError
14
+ import pyramid_basemodel
15
+
16
+ from pyramid_fullauth.views import BaseView
17
+ from pyramid_fullauth.models import User
18
+ from pyramid_fullauth.models import AuthenticationProvider
19
+ from pyramid_fullauth.events import BeforeSocialRegister
20
+ from pyramid_fullauth.events import AfterSocialRegister
21
+ from pyramid_fullauth.events import AfterSocialLogIn
22
+ from pyramid_fullauth.events import SocialAccountAlreadyConnected
23
+ from pyramid_fullauth import tools
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ @view_config(context='velruse.AuthenticationComplete',
29
+ permission=NO_PERMISSION_REQUIRED,
30
+ renderer="pyramid_fullauth:resources/templates/register.mako")
31
+ class SocialLoginViews(BaseView):
32
+
33
+ """Social login views definition."""
34
+
35
+ def set_provider(self, user, provider_name, user_provider_id):
36
+ """
37
+ Set authentication provider on user.
38
+
39
+ This method will connect given provider with given user,
40
+ unless provider_id has already been used on another user.
41
+
42
+ :param pyramid_fullauth.user.User user: user object
43
+ :param str provider_name: provider name
44
+ :param str user_provider_id: user id delivered by given provider
45
+
46
+ :returns: whether user got/was connected or the connection was made with another user.
47
+ :rtype: bool
48
+ """
49
+ if user.id:
50
+ try:
51
+ provider_auth = pyramid_basemodel.Session.query(
52
+ AuthenticationProvider
53
+ ).filter(
54
+ AuthenticationProvider.user_id == user.id,
55
+ AuthenticationProvider.provider == provider_name
56
+ ).one()
57
+ if provider_auth.provider_id != user_provider_id:
58
+ return False
59
+ return True
60
+ except NoResultFound:
61
+ pass
62
+
63
+ provider_auth = AuthenticationProvider(
64
+ provider=provider_name,
65
+ provider_id=user_provider_id
66
+ )
67
+ user.providers.append(provider_auth)
68
+ pyramid_basemodel.Session.flush()
69
+ return True
70
+
71
+ def __call__(self):
72
+ """
73
+ Action provides social authorization functionality.
74
+
75
+ When authorization with facebook or twitter is done successfully
76
+ action tries to find existing user in database,
77
+ if it exists - login this user, otherwise creates new user.
78
+ """
79
+ context = self.request.context
80
+ response_values = {
81
+ 'status': False,
82
+ 'csrf_token': self.request.session.get_csrf_token()
83
+ }
84
+ user = self.request.user
85
+
86
+ if user:
87
+ # Lets try to connect our user
88
+ return self._connect_user(response_values)
89
+
90
+ else:
91
+ try:
92
+ user = pyramid_basemodel.Session.query(
93
+ User
94
+ ).join(AuthenticationProvider).filter(
95
+ AuthenticationProvider.provider == context.provider_name,
96
+ AuthenticationProvider.provider_id == context.profile['accounts'][0]['userid']
97
+ ).one()
98
+ except NoResultFound:
99
+ user = None
100
+
101
+ # If the user for the provider was not found then check
102
+ # if in the DB exists user with the same email
103
+ if not user:
104
+ user = self._register_user()
105
+ try:
106
+ self.request.registry.notify(
107
+ AfterSocialRegister(
108
+ self.request, user, context.profile, response_values))
109
+ except HTTPFound as redirect:
110
+ # it's a redirect, let's follow it!
111
+ return redirect
112
+
113
+ # if we're here, user exists,
114
+ try:
115
+ self.request.registry.notify(AfterSocialLogIn(self.request, user, context.profile))
116
+ except HTTPFound as redirect:
117
+ # it's a redirect, let's follow it!
118
+ return self.request.login_perform(user, location=redirect.location)
119
+ else:
120
+ return self.request.login_perform(user)
121
+
122
+ def _connect_user(self, response_values):
123
+ """
124
+ Connect user to social account.
125
+
126
+ :param dict response_values:
127
+
128
+ :returns: response values with any message,
129
+ or HTTPFound if raised in SocialAccountAlreadyConnected
130
+ :rtype: dict
131
+ """
132
+ context = self.request.context
133
+ user = self.request.user
134
+ try:
135
+ if not self.set_provider(
136
+ user, context.provider_name, context.profile['accounts'][0]['userid']
137
+ ):
138
+ response_values['msg'] = self.request._(
139
+ 'Your account is already connected to other ${provider} account.',
140
+ domain='pyramid_fullauth',
141
+ mapping={'provider': context.provider_name}
142
+ )
143
+ else:
144
+ response_values['status'] = True
145
+ response_values['msg'] = self.request._(
146
+ 'Your account has been connected to ${provider} account.',
147
+ domain='pyramid_fullauth',
148
+ mapping={'provider': context.provider_name}
149
+ )
150
+ except IntegrityError:
151
+ response_values['msg'] = self.request._(
152
+ 'This ${provider} account is already connected with other account.',
153
+ domain='pyramid_fullauth',
154
+ mapping={'provider': context.provider_name}
155
+ )
156
+ try:
157
+ self.request.registry.notify(
158
+ SocialAccountAlreadyConnected(
159
+ self.request, user, context.profile, response_values))
160
+ except HTTPFound as redirect:
161
+ # it's a redirect, let's follow it!
162
+ return redirect
163
+ return response_values
164
+
165
+ def _register_user(self):
166
+ """Actually register new user in the system based on context values."""
167
+ context = self.request.context
168
+ email = self._email_from_context(context)
169
+
170
+ try:
171
+ user = pyramid_basemodel.Session.query(User).filter(User.email == email).one()
172
+ # If we are here that means that in the DB exists user with the same email but without the provider
173
+ # then we connect social account to this user
174
+ if not self.set_provider(
175
+ user, context.provider_name, context.profile['accounts'][0]['userid']
176
+ ):
177
+ # authenticating user with different social account than assigned,
178
+ # recogniced by same email address used
179
+ logger.debug('''Authenticated {user.id} connected to
180
+ {context.provider_name} id {connected_id},
181
+ with {userid}'''.format(
182
+ user=user,
183
+ context=context,
184
+ connected_id=user.provider_id(context.provider_name),
185
+ userid=context.profile['accounts'][0]['userid']))
186
+ pyramid_basemodel.Session.flush()
187
+ except NoResultFound:
188
+ length_min = self.config.register.password.length_min
189
+ user = User(
190
+ email=email,
191
+ password=tools.password_generator(length_min),
192
+ address_ip=self.request.remote_addr
193
+ )
194
+ self.request.registry.notify(BeforeSocialRegister(self.request, user, context.profile))
195
+ self.set_provider(user, context.provider_name, context.profile['accounts'][0]['userid'])
196
+ pyramid_basemodel.Session.add(user)
197
+ pyramid_basemodel.Session.flush()
198
+ user.is_active = True
199
+ return user
200
+
201
+ def _email_from_context(self, context):
202
+ """
203
+ Extract or generate email from context values.
204
+
205
+ :param velruse.AuthenticationComplete context: velruse context
206
+ """
207
+ # getting verified email from provider
208
+ if 'verifiedEmail' in context.profile:
209
+ return context.profile['verifiedEmail']
210
+ # getting first of the emails provided by social login provider
211
+ elif 'emails' in context.profile and context.profile['emails'] and 'value' in context.profile['emails'][0]:
212
+ return context.profile['emails'][0]['value']
213
+ # generating some random email address based on social userid and provider domain
214
+ else:
215
+ return u'{0}@{1}'.format(
216
+ context.profile['accounts'][0]['userid'],
217
+ context.profile['accounts'][0]['domain']
218
+ )
Binary file
tests/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Tests."""
tests/__init__.pyc ADDED
Binary file
tests/conftest.py ADDED
@@ -0,0 +1,190 @@
1
+ """Most of the fixtures needed."""
2
+ from mock import Mock
3
+ import pytest
4
+
5
+ import transaction
6
+ from sqlalchemy import create_engine
7
+ from sqlalchemy.orm import scoped_session, sessionmaker
8
+ from sqlalchemy.pool import NullPool
9
+ from zope.sqlalchemy import ZopeTransactionExtension
10
+
11
+ from pyramid.compat import text_type
12
+ from pytest_pyramid import factories
13
+ import pyramid_basemodel
14
+
15
+
16
+ @pytest.fixture
17
+ def web_request():
18
+ """Mocked web request for views testing."""
19
+ request = Mock()
20
+ config = Mock()
21
+ config.configure_mock(
22
+ **{'fullauth.register.password':
23
+ {'length_min': 8, 'confirm': True},
24
+ 'POST': {'confirm_password': '987654321'}
25
+ }
26
+ )
27
+
28
+ def _(message, *args, **kwargs):
29
+ return message
30
+ request._ = Mock(side_effect=_)
31
+ request.configure_mock(
32
+ **{'registry': {'config': config}}
33
+ )
34
+
35
+ return request
36
+
37
+
38
+ @pytest.fixture(scope='function', params=['sqlite', 'mysql', 'postgresql'])
39
+ def db_session(request):
40
+ """SQLAlchemy session."""
41
+ from pyramid_fullauth.models import Base
42
+
43
+ if request.param == 'sqlite':
44
+ connection = 'sqlite:///fullauth.sqlite'
45
+ elif request.param == 'mysql':
46
+ request.getfuncargvalue('mysqldb') # takes care of creating database
47
+ connection = 'mysql+mysqldb://root:@127.0.0.1:3307/tests?charset=utf8'
48
+ elif request.param == 'postgresql':
49
+ request.getfuncargvalue('postgresql') # takes care of creating database
50
+ connection = 'postgresql+psycopg2://postgres:@127.0.0.1:5433/tests'
51
+
52
+ engine = create_engine(connection, echo=False, poolclass=NullPool)
53
+ pyramid_basemodel.Session = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
54
+ pyramid_basemodel.bind_engine(engine, pyramid_basemodel.Session, should_drop=True)
55
+
56
+ def destroy():
57
+ transaction.commit()
58
+ Base.metadata.drop_all(engine)
59
+
60
+ request.addfinalizer(destroy)
61
+
62
+ return pyramid_basemodel.Session
63
+
64
+
65
+ @pytest.fixture
66
+ def user(db_session):
67
+ """Default user."""
68
+ from pyramid_fullauth.models import User
69
+ from tests.tools import DEFAULT_USER
70
+ user = User(**DEFAULT_USER)
71
+ db_session.add(user)
72
+ transaction.commit()
73
+ return user
74
+
75
+
76
+ @pytest.fixture
77
+ def active_user(user, db_session):
78
+ """Active user."""
79
+ user = db_session.merge(user)
80
+ user.is_active = True
81
+ transaction.commit()
82
+ return user
83
+
84
+
85
+ @pytest.fixture(params=[
86
+ # (an @ character must separate the local and domain parts)
87
+ text_type('Abc.example.com'),
88
+ # (character dot(.) is last in local part)
89
+ text_type('Abc.@example.com'),
90
+ # (character dot(.) is double)
91
+ text_type('Abc..123@example.com'),
92
+ # (only one @ is allowed outside quotation marks)
93
+ text_type('A@b@c@example.com'),
94
+ # (none of the special characters in this local part is allowed outside quotation marks)
95
+ text_type('a"b(c)d,e:f;g<h>i[j\k]l@example.com'),
96
+ # (quoted strings must be dot separated, or the only element making up the local-part)
97
+ text_type('just"not"right@example.com'),
98
+ # (spaces, quotes, and backslashes may only exist when within quoted strings and preceded by a backslash)
99
+ text_type('this is"not\allowed@example.com'),
100
+ # (even if escaped (preceded by a backslash), spaces, quotes, and backslashes must still be contained by quotes)
101
+ text_type('this\ still\"not\\allowed@example.com'),
102
+ text_type('bad-mail'),
103
+ ])
104
+ def invalid_email(request):
105
+ """Parametrized fixture with all the incorrect emails."""
106
+ return request.param
107
+
108
+
109
+ default_config = factories.pyramid_config({
110
+ 'pyramid.includes': [
111
+ 'pyramid_tm',
112
+ 'pyramid_fullauth'
113
+ ]
114
+ })
115
+
116
+
117
+ extended_config = factories.pyramid_config({
118
+ 'pyramid.includes': [
119
+ 'pyramid_tm',
120
+ 'pyramid_fullauth',
121
+ 'tests.tools.include_views'
122
+ ]
123
+ })
124
+
125
+
126
+ short_config = factories.pyramid_config({
127
+ 'yml.location': 'tests:config/short_memory.yaml',
128
+ 'pyramid.includes': [
129
+ 'pyramid_tm',
130
+ 'tzf.pyramid_yml',
131
+ 'pyramid_fullauth',
132
+ 'tests.tools.include_views'
133
+ ]
134
+ })
135
+
136
+
137
+ social_config = factories.pyramid_config({
138
+ 'yml.location': 'tests:config/social.yaml',
139
+ 'pyramid.includes': [
140
+ 'pyramid_tm',
141
+ 'tzf.pyramid_yml',
142
+ 'pyramid_fullauth',
143
+ 'tests.tools.include_views'
144
+ ]
145
+ })
146
+
147
+
148
+ authable_config = factories.pyramid_config({
149
+ 'yml.location': 'tests:config',
150
+ 'env': 'login',
151
+ 'pyramid.includes': [
152
+ 'pyramid_tm',
153
+ 'tzf.pyramid_yml',
154
+ 'pyramid_fullauth',
155
+ 'tests.tools.include_views'
156
+ ]
157
+ })
158
+
159
+
160
+ nopassconfirm_config = factories.pyramid_config({
161
+ 'yml.location': 'tests:config/no_password_confirm.yaml',
162
+ 'env': 'login',
163
+ 'pyramid.includes': [
164
+ 'pyramid_tm',
165
+ 'tzf.pyramid_yml',
166
+ 'pyramid_fullauth',
167
+ 'tests.tools.include_views'
168
+ ]
169
+ })
170
+
171
+
172
+ nopassregister_config = factories.pyramid_config({
173
+ 'yml.location': 'tests:config/no_password_register.yaml',
174
+ 'env': 'login',
175
+ 'pyramid.includes': [
176
+ 'pyramid_tm',
177
+ 'tzf.pyramid_yml',
178
+ 'pyramid_fullauth',
179
+ 'tests.tools.include_views'
180
+ ]
181
+ })
182
+
183
+
184
+ default_app = factories.pyramid_app('default_config')
185
+ extended_app = factories.pyramid_app('extended_config')
186
+ short_app = factories.pyramid_app('short_config')
187
+ social_app = factories.pyramid_app('social_config')
188
+ authable_app = factories.pyramid_app('authable_config')
189
+ nopassconfirm_app = factories.pyramid_app('nopassconfirm_config')
190
+ nopassregister_app = factories.pyramid_app('nopassregister_config')
tests/conftest.pyc ADDED
Binary file