pyramid-fullauth 0.2.3__py27-none-any.whl

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 (65) hide show
  1. pyramid_fullauth/__init__.py +91 -0
  2. pyramid_fullauth/auth.py +93 -0
  3. pyramid_fullauth/config/config.yml +26 -0
  4. pyramid_fullauth/events.py +255 -0
  5. pyramid_fullauth/exceptions.py +54 -0
  6. pyramid_fullauth/models/__init__.py +187 -0
  7. pyramid_fullauth/models/mixins/__init__.py +9 -0
  8. pyramid_fullauth/models/mixins/email.py +75 -0
  9. pyramid_fullauth/models/mixins/password.py +144 -0
  10. pyramid_fullauth/request.py +65 -0
  11. pyramid_fullauth/resources/helpers/social.mako +17 -0
  12. pyramid_fullauth/resources/locale/pyramid_fullauth.pot +203 -0
  13. pyramid_fullauth/resources/templates/403.mako +11 -0
  14. pyramid_fullauth/resources/templates/_form.login.mako +44 -0
  15. pyramid_fullauth/resources/templates/_form.register.mako +47 -0
  16. pyramid_fullauth/resources/templates/_social.login.mako +17 -0
  17. pyramid_fullauth/resources/templates/activate.mako +14 -0
  18. pyramid_fullauth/resources/templates/email_change.mako +33 -0
  19. pyramid_fullauth/resources/templates/layout.mako +13 -0
  20. pyramid_fullauth/resources/templates/login.mako +14 -0
  21. pyramid_fullauth/resources/templates/register.mako +22 -0
  22. pyramid_fullauth/resources/templates/reset.mako +34 -0
  23. pyramid_fullauth/resources/templates/reset.proceed.mako +41 -0
  24. pyramid_fullauth/routing/__init__.py +6 -0
  25. pyramid_fullauth/routing/predicates.py +70 -0
  26. pyramid_fullauth/tools.py +68 -0
  27. pyramid_fullauth/views/__init__.py +16 -0
  28. pyramid_fullauth/views/basic/__init__.py +6 -0
  29. pyramid_fullauth/views/basic/forbidden.py +50 -0
  30. pyramid_fullauth/views/basic/login.py +123 -0
  31. pyramid_fullauth/views/basic/profile.py +205 -0
  32. pyramid_fullauth/views/basic/register.py +144 -0
  33. pyramid_fullauth/views/social.py +138 -0
  34. pyramid_fullauth-0.2.3.dist-info/DESCRIPTION.rst +124 -0
  35. pyramid_fullauth-0.2.3.dist-info/METADATA +160 -0
  36. pyramid_fullauth-0.2.3.dist-info/RECORD +65 -0
  37. pyramid_fullauth-0.2.3.dist-info/WHEEL +5 -0
  38. pyramid_fullauth-0.2.3.dist-info/pydist.json +1 -0
  39. pyramid_fullauth-0.2.3.dist-info/top_level.txt +2 -0
  40. tests/__init__.py +0 -0
  41. tests/cases/__init__.py +0 -0
  42. tests/cases/conftest.py +47 -0
  43. tests/cases/test_integration/__init__.py +0 -0
  44. tests/cases/test_integration/conftest.py +78 -0
  45. tests/cases/test_integration/test_basic.py +7 -0
  46. tests/cases/test_integration/test_view_email.py +85 -0
  47. tests/cases/test_integration/test_view_login.py +322 -0
  48. tests/cases/test_integration/test_view_register.py +365 -0
  49. tests/cases/test_integration/test_view_reset.py +109 -0
  50. tests/cases/test_unit/__init__.py +0 -0
  51. tests/cases/test_unit/conftest.py +12 -0
  52. tests/cases/test_unit/test_groupfinder.py +19 -0
  53. tests/cases/test_unit/test_tools.py +21 -0
  54. tests/cases/test_unit/test_user_active.py +30 -0
  55. tests/cases/test_unit/test_user_admin.py +55 -0
  56. tests/cases/test_unit/test_user_email.py +21 -0
  57. tests/cases/test_unit/test_user_password.py +55 -0
  58. tests/cases/test_unit/test_user_providers.py +21 -0
  59. tests/cases/test_unit/test_user_repr.py +28 -0
  60. tests/cases/test_unit/test_validators.py +95 -0
  61. tests/config/config.login.yml +4 -0
  62. tests/config/config.np.yml +4 -0
  63. tests/config/config.pc.yml +5 -0
  64. tests/config/config.yml +14 -0
  65. tests/utils.py +111 -0
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2013 by pyramid_fullauth authors and contributors <see AUTHORS file>
4
+ #
5
+ # This module is part of pyramid_fullauth and is released under
6
+ # the MIT License (MIT): http://opensource.org/licenses/MIT
7
+
8
+ import logging
9
+
10
+ from tzf.pyramid_yml import config_defaults
11
+ from pyramid.authorization import ACLAuthorizationPolicy
12
+ from pyramid.authentication import AuthTktAuthenticationPolicy
13
+ from pyramid.session import UnencryptedCookieSessionFactoryConfig
14
+
15
+
16
+ from pyramid_fullauth.auth import groupfinder
17
+ from pyramid_fullauth.routing import predicates
18
+ from pyramid_fullauth.request import login_perform
19
+ from pyramid_fullauth.request import user
20
+
21
+ __version__ = '0.2.3'
22
+
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ def includeme(configurator):
28
+ '''
29
+ pyramid_fullauth includeme method
30
+
31
+ :param pyramid.configurator.Configurator configurator: pyramid's configurator object
32
+ '''
33
+
34
+ config_defaults(configurator, 'pyramid_fullauth:config')
35
+ configurator.include('pyramid_localize')
36
+ configurator.include('pyramid_mako')
37
+ fullauth_config = configurator.registry['config'].fullauth
38
+
39
+ configurator.set_authorization_policy(ACLAuthorizationPolicy())
40
+ configurator.set_authentication_policy(
41
+ AuthTktAuthenticationPolicy(callback=groupfinder,
42
+ **fullauth_config.AuthTkt))
43
+
44
+ # loading and setting session factory
45
+ # first, divide provided path for module, and factory name
46
+ module, factory = fullauth_config.session.factory.rsplit('.', 1)
47
+ # import session module first
48
+ session_module = __import__(module, fromlist=[module])
49
+ # get the factory class
50
+ session_factory = getattr(session_module, factory)
51
+
52
+ # set the new session factory
53
+ configurator.set_session_factory(
54
+ session_factory(**fullauth_config.session.settings))
55
+
56
+ configurator.add_view_predicate('check_csrf', predicates.CSRFCheckPredicate)
57
+
58
+ # add routes
59
+ configurator.add_route(name='login', pattern='/login')
60
+ configurator.add_route(name='logout', pattern='/logout')
61
+ configurator.add_route(name='register', pattern='/register')
62
+ configurator.add_route(name='register:activate', pattern='/register/activate/{hash}')
63
+ configurator.add_route(name='password:reset', pattern='/password/reset')
64
+ configurator.add_route(name='password:reset:continue', pattern='/password/reset/{hash}',
65
+ custom_predicates=(predicates.reset_hash,))
66
+ configurator.add_route(name='email:change', pattern='/email/change')
67
+ configurator.add_route(name='email:change:continue', pattern='/email/change/{hash}',
68
+ custom_predicates=(predicates.change_email_hash,))
69
+ # scan base views
70
+ configurator.scan('pyramid_fullauth.views.basic')
71
+
72
+ # check for the social. If social is not available, we will not turn it on!
73
+ if 'social' in fullauth_config:
74
+ # Velruse init (for social auth)
75
+
76
+ # scan social views
77
+ configurator.scan('pyramid_fullauth.views.social')
78
+ providers = fullauth_config.social
79
+ configurator.registry['config']['login_providers'] = providers
80
+ for provider in providers:
81
+ # Ugly hack for using google oauth2, not OpenID + Oauth2 from google
82
+ provider_settings = fullauth_config['social'][provider]
83
+ if provider == 'google': # pragma: no cover
84
+ provider = 'google_oauth2'
85
+
86
+ configurator.include('velruse.providers.' + provider)
87
+ getattr(configurator, 'add_{0}_login'.format(provider))(**provider_settings)
88
+
89
+ # we'll add some request methods:
90
+ configurator.add_request_method(login_perform, name='login_perform')
91
+ configurator.add_request_method(user, name='user', reify=True)
@@ -0,0 +1,93 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2013 by pyramid_fullauth authors and contributors <see AUTHORS file>
4
+ #
5
+ # This module is part of pyramid_fullauth and is released under
6
+ # the MIT License (MIT): http://opensource.org/licenses/MIT
7
+
8
+ from pyramid.security import Allow
9
+ from pyramid.security import Deny
10
+ from pyramid.security import Everyone
11
+ from pyramid.security import ALL_PERMISSIONS
12
+ from pyramid.security import forget
13
+
14
+
15
+ def groupfinder(userid, request):
16
+ '''
17
+ Reads all users groups,
18
+
19
+ .. note::
20
+
21
+ Adds **s:inactive** group to users who has not activated their account, and **s:user** group to those, who did.
22
+ If user has is_admin flag, he gets **s:superadmin** group set
23
+
24
+ Might be useful, when you want restrict access to some parts of your application, but still allow log in, and access to some other parts.
25
+
26
+ :param int userid: user identity
27
+ :param pyramid.request.Request request: request object
28
+ :returns: list of groups
29
+ :rtype: list
30
+ '''
31
+
32
+ user = request.user
33
+ groups = []
34
+ if user and user.id == userid:
35
+ groups = [group.name for group in user.groups]
36
+
37
+ # let's add inactive group for users that have not activated their account
38
+
39
+ if user.is_admin:
40
+ groups.append('s:superadmin')
41
+
42
+ if user.is_active:
43
+ groups.append('s:user')
44
+ else:
45
+ groups.append('s:inactive')
46
+
47
+ return groups
48
+
49
+
50
+ class BaseACLRootFactoryMixin(object):
51
+
52
+ '''
53
+ ACL list factory Mixin,
54
+ __acl__ is the attribute which stores the list.
55
+
56
+ :return: tuple (Allow|Deny, Group name, Permission)
57
+ :rtype: list
58
+
59
+ .. note::
60
+
61
+ Can be converted later to database stored (sqlalchemy session is accessible through request.db)
62
+ '''
63
+
64
+ __acl__ = [(Allow, Everyone, 'view'),
65
+ (Allow, 's:superadmin', ALL_PERMISSIONS),
66
+ (Allow, 's:user', ('password_change', 'email_change'))
67
+ ]
68
+
69
+ def __init__(self, request):
70
+ self.request = request
71
+
72
+
73
+ class force_logout(object):
74
+
75
+ '''
76
+ Logs out user.
77
+ '''
78
+
79
+ def __call__(self, wrapped_view):
80
+
81
+ def decorator(*args, **kwargs):
82
+ if not args:
83
+ return wrapped_view(*args, **kwargs)
84
+
85
+ for arg in args:
86
+ if 'request' in dir(arg):
87
+ if arg.request.user:
88
+ arg.request.response.headerlist.extend(forget(arg.request))
89
+ arg.request.user = None
90
+ data = wrapped_view(*args, **kwargs)
91
+ return data
92
+
93
+ return decorator
@@ -0,0 +1,26 @@
1
+ # Copyright (c) 2013 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
+
6
+ # pyramid_fullauth's default configuration
7
+ fullauth:
8
+ check_csrf: True # Whether login processes should work with csrf token, or without
9
+ register:
10
+ password:
11
+ require: True # set to false to not read password during register, and generate random one
12
+ length_min: 6 # will be used either to check password's length or generate this length random password
13
+ confirm: True # by default there will be a field for password confirmation on the registration form
14
+ AuthTkt:
15
+ secret: fullauth_psst # default secret used to hash auth_tk cookie
16
+ hashalg: sha512 # default authentication policy hash algorithm
17
+ login:
18
+ cookie_max_age: 2592000 # 30 days
19
+ redirects: # route name, to redirect to. If False, then redirects just to /
20
+ logout: False
21
+ session: # session factory settings
22
+ # factory key is responsible for providing full path to factory class (module.submodule.SessionFactory)
23
+ factory: pyramid.session.UnencryptedCookieSessionFactoryConfig
24
+ # settings are key: value pairs of all factory initialize attributes
25
+ settings:
26
+ secret: THATS_NOT_SECRET_ITS_A_SECRET
@@ -0,0 +1,255 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2013 by pyramid_fullauth authors and contributors <see AUTHORS file>
4
+ #
5
+ # This module is part of pyramid_fullauth and is released under
6
+ # the MIT License (MIT): http://opensource.org/licenses/MIT
7
+
8
+ '''
9
+ pyramid_fullauth emits these events during whole cycle.
10
+ '''
11
+
12
+
13
+ class _BaseRegisterEvent(object):
14
+
15
+ '''
16
+ Base fullauth - most of the fullauth's event will provide both request and suer object with some additional data (these will be described then)
17
+ '''
18
+
19
+ def __init__(self, request, user):
20
+ '''
21
+
22
+ :param pyramid.request.Request request: request object
23
+ :param pyramid_fullauth.models.User user: user object
24
+ '''
25
+ self.request = request
26
+ self.user = user
27
+
28
+
29
+ class BeforeRegister(_BaseRegisterEvent):
30
+
31
+ '''
32
+ BeforeRegister event, fired, so developers can add custom validation
33
+ User object is not yet defined
34
+ '''
35
+
36
+ def __init__(self, request, user, errors):
37
+ '''
38
+
39
+ :param pyramid.request.Request request: request object
40
+ :param pyramid_fullauth.models.User user: user object
41
+ :param dict errors: a dictionary with wrong/not submitted fields
42
+ with format - fields for which error occured: error message
43
+ '''
44
+
45
+ _BaseRegisterEvent.__init__(self, request, user)
46
+ self.errors = errors
47
+
48
+
49
+ class AfterRegister(_BaseRegisterEvent):
50
+
51
+ '''
52
+ AfterRegister event, fired so developers can add some custom post-processing, like e-mail sending
53
+ User object is already in a session.
54
+
55
+ .. note::
56
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
57
+
58
+ .. warning::
59
+ If HTTPFound is risen from event listener, then response_values will not be used!
60
+
61
+ '''
62
+
63
+ def __init__(self, request, user, response_values):
64
+ '''
65
+
66
+ :param pyramid.request.Request request: request object
67
+ :param pyramid_fullauth.models.User user: user object
68
+ :param dict response_values: a dictionary with response values
69
+ '''
70
+ _BaseRegisterEvent.__init__(self, request, user)
71
+ self.response_values = response_values
72
+
73
+
74
+ class AfterActivate(_BaseRegisterEvent):
75
+
76
+ '''
77
+ Events gets emitted after account activation. To send a greeting email, or other actions that could be taken
78
+
79
+ .. note::
80
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
81
+ '''
82
+ pass
83
+
84
+
85
+ class AfterResetRequest(_BaseRegisterEvent):
86
+
87
+ '''
88
+ Event gets fired when the user requires password reset
89
+
90
+ .. note::
91
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
92
+ '''
93
+ pass
94
+
95
+
96
+ class BeforeReset(_BaseRegisterEvent):
97
+
98
+ '''
99
+ Event gets fired when user resets own password, fired so developer can add custom validation (like password length)
100
+ '''
101
+ pass
102
+
103
+
104
+ class AfterReset(_BaseRegisterEvent):
105
+
106
+ '''
107
+ Event gets fired when user resets own password
108
+
109
+ .. note::
110
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
111
+ '''
112
+ pass
113
+
114
+
115
+ class AlreadyLoggedIn(object):
116
+
117
+ '''
118
+ Event gets fired when the logged in user enters login page
119
+
120
+ .. note::
121
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
122
+ '''
123
+
124
+ def __init__(self, request):
125
+ '''
126
+ :param pyramid.request.Request request: request object
127
+ '''
128
+ self.request = request
129
+
130
+
131
+ class BeforeLogIn(_BaseRegisterEvent):
132
+
133
+ '''
134
+ Event gets fired before the user logs in
135
+
136
+ .. note::
137
+ Action emitting this event, should catch all AttributeError that might be risen in event listener.
138
+ User param set to None when user is not found or request method is GET.
139
+ '''
140
+ pass
141
+
142
+
143
+ class AfterLogIn(_BaseRegisterEvent):
144
+
145
+ '''
146
+ Event gets fired when the user logs in
147
+ '''
148
+ pass
149
+
150
+
151
+ # Social events
152
+ # TODO: extract to sub module
153
+
154
+
155
+ class _BaseSocialRegister(_BaseRegisterEvent):
156
+
157
+ '''
158
+ Base for all social requests
159
+ '''
160
+
161
+ def __init__(self, request, user, profile):
162
+ '''
163
+
164
+ :param pyramid.request.Request request: request object
165
+ :param pyramid_fullauth.models.User user: user object
166
+ :param dict profile: a dictionary with profile data
167
+ '''
168
+ _BaseRegisterEvent.__init__(self, request, user)
169
+ self.profile = profile
170
+
171
+
172
+ class BeforeSocialRegister(_BaseSocialRegister):
173
+
174
+ '''
175
+ BeforeRegister event, fired, so developers can add custom validation
176
+ '''
177
+ pass
178
+
179
+
180
+ class AfterSocialRegister(_BaseSocialRegister):
181
+
182
+ '''
183
+ AfterSocialRegister events is emitted after user registers through one of the social networks
184
+
185
+ .. note::
186
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
187
+ '''
188
+
189
+ def __init__(self, request, user, profile, response_values):
190
+ '''
191
+
192
+ :param pyramid.request.Request request: request object
193
+ :param pyramid_fullauth.models.User user: user object
194
+ :param dict profile: a dictionary with profile data
195
+ :param dict response_values: a dictionary with response values
196
+ '''
197
+ _BaseSocialRegister.__init__(self, request, user, profile)
198
+ self.response_values = response_values
199
+
200
+
201
+ class AfterSocialLogIn(_BaseSocialRegister):
202
+
203
+ '''
204
+ Event gets fired when the user logs in through social network
205
+
206
+ .. note::
207
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
208
+ '''
209
+ pass
210
+
211
+
212
+ class SocialAccountAlreadyConnected(_BaseSocialRegister):
213
+
214
+ '''
215
+ Event gets fired when the user try to connect social network to account but this social account is already connected to another account
216
+
217
+ .. note::
218
+ Action emitting this event, should catch all HTTPFound that might be risen in event listener.
219
+ '''
220
+
221
+ def __init__(self, request, user, profile, response_values):
222
+ '''
223
+
224
+ :param pyramid.request.Request request: request object
225
+ :param pyramid_fullauth.models.User user: user object
226
+ :param dict profile: a dictionary with profile data
227
+ :param dict response_values: a dictionary with response values
228
+ '''
229
+ _BaseSocialRegister.__init__(self, request, user, profile)
230
+ self.response_values = response_values
231
+ pass
232
+
233
+
234
+ class BeforeEmailChange(_BaseRegisterEvent):
235
+
236
+ '''
237
+ BeforeEmailChange event, fired so developers can add custom validation (like checking password)
238
+ '''
239
+ pass
240
+
241
+
242
+ class AfterEmailChange(_BaseRegisterEvent):
243
+
244
+ '''
245
+ AfterEmailChange event, fired so developers can add some custom post-processing, like e-mail sending
246
+ '''
247
+ pass
248
+
249
+
250
+ class AfterEmailChangeActivation(_BaseRegisterEvent):
251
+
252
+ '''
253
+ AfterEmailChangeActivation event, fired when user activate new email addres, so developers can add some custom post-processing
254
+ '''
255
+ pass
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2013 by pyramid_fullauth authors and contributors <see AUTHORS file>
4
+ #
5
+ # This module is part of pyramid_fullauth and is released under
6
+ # the MIT License (MIT): http://opensource.org/licenses/MIT
7
+
8
+
9
+ class DeleteException(Exception):
10
+
11
+ '''
12
+ Exception risen when the user can't be deleted
13
+ '''
14
+ pass
15
+
16
+
17
+ class ValidateError(ValueError):
18
+
19
+ '''
20
+ Base of every validate error in pyramid_fullauth
21
+ '''
22
+ pass
23
+
24
+
25
+ class EmptyError(ValidateError):
26
+
27
+ '''
28
+ Thrown whenever user is trying to set empty value
29
+ '''
30
+ pass
31
+
32
+
33
+ class ShortPasswordError(ValidateError):
34
+
35
+ '''
36
+ Thrown when password doesn't meet the length requirement
37
+ '''
38
+ pass
39
+
40
+
41
+ class PasswordConfirmMismatchError(ValidateError):
42
+
43
+ '''
44
+ Thrown when there's a mismatch with cpassword_confirm
45
+ '''
46
+ pass
47
+
48
+
49
+ class EmailValidationError(ValidateError):
50
+
51
+ '''
52
+ Exception thrown, when there's incorrect email provided
53
+ '''
54
+ pass