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,34 @@
1
+ ## -*- coding: utf-8 -*-
2
+ <%doc>
3
+ Copyright (c) 2013 - 2014 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
+ </%doc>
8
+ <%inherit file="pyramid_fullauth:resources/templates/layout.mako" />
9
+
10
+ <h1>${_('Recover your password', domain='pyramid_fullauth')}</h1>
11
+ <div class="row-fluid">
12
+ <div class="span2"></div>
13
+ <div class="span8">
14
+ % if not status:
15
+ <div class="alert alert-error">${_('Error!', domain='pyramid_fullauth')} ${msg}</div>
16
+ % endif
17
+ <form class="form-horizontal" name="reset_password" method="POST" action="${request.current_route_path()}">
18
+ <fieldset>
19
+ <div class="control-group">
20
+ <label class="control-label" for="reset[email]">${_('Your e-mail address', domain='pyramid_fullauth')}:</label>
21
+ <div class="controls">
22
+ <input type="email" placeholder="username@hostname.com" name="email" id="reset[email]"/>
23
+ <input type="hidden" name="csrf_token" value="${csrf_token}" />
24
+ </div>
25
+ </div>
26
+ <div class="form-actions">
27
+ <button type="submit" class="btn btn-large">${_('Reset Password', domain='pyramid_fullauth')}</button>
28
+ </div>
29
+ </fieldset>
30
+ </form>
31
+ </div>
32
+ <div class="span2"></div>
33
+ </div>
34
+
@@ -0,0 +1,41 @@
1
+ ## -*- coding: utf-8 -*-
2
+ <%doc>
3
+ Copyright (c) 2013 - 2014 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
+ </%doc>
8
+ <%inherit file="pyramid_fullauth:resources/templates/layout.mako" />
9
+
10
+ <h1>${_('Recover your password - choose new password', domain='pyramid_fullauth')}</h1>
11
+ <div class="row-fluid">
12
+ <div class="span8">
13
+ % if not status:
14
+ <div class="alert alert-error">${_('Error!', domain='pyramid_fullauth')} ${msg}</div>
15
+ % endif
16
+ <form class="form-horizontal" id="reset_password" name="reset_password" method="POST" action="${request.current_route_path()}">
17
+ <input type="hidden" name="csrf_token" value="${csrf_token}" />
18
+ <fieldset>
19
+ <div class="control-group">
20
+ <label class="control-label" for="password">${_('Password', domain='pyramid_fullauth')}:</label>
21
+ <div class="controls">
22
+ <input type="password" id="password" name="password" placeholder="minimum 6 characters"/>
23
+ <span class="help-inline" id="password_status"></span>
24
+ </div>
25
+ </div>
26
+ <div class="control-group">
27
+ <label class="control-label" for="confirm_password">${_('Confirm password', domain='pyramid_fullauth')}:</label>
28
+ <div class="controls">
29
+ <input type="password" name="confirm_password" id="confirm_password"/>
30
+ <span class="help-inline" id="confirm_password_status"></span>
31
+ </div>
32
+ </div>
33
+ <div class="form-actions">
34
+ <button type="submit" class="btn btn-large">${_('Reset Password', domain='pyramid_fullauth')}</button>
35
+ </div>
36
+ </fieldset>
37
+ </form>
38
+ </div>
39
+ <div class="span2"></div>
40
+ </div>
41
+
@@ -0,0 +1,5 @@
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
+ """Routing module."""
Binary file
@@ -0,0 +1,86 @@
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
+ """Routing predicate definitions."""
6
+
7
+ from sqlalchemy.orm.exc import NoResultFound
8
+ from pyramid.config.predicates import CheckCSRFTokenPredicate
9
+ from pyramid.httpexceptions import HTTPUnauthorized
10
+ import pyramid_basemodel
11
+
12
+ from pyramid_fullauth.models import User
13
+
14
+
15
+ def reset_hash(info, request):
16
+ """
17
+ Check whether reset hash is correct.
18
+
19
+ :param dict info: pyramid info dict with path fragments and info
20
+ :param pyramid.request.Request request: request object
21
+
22
+ :returns: whether reset hash exists or not
23
+ :rtype: bool
24
+
25
+ """
26
+ reset_hash = info['match'].get('hash', None)
27
+ if reset_hash:
28
+ try:
29
+ info['match']['user'] = pyramid_basemodel.Session.query(User).filter(User.reset_key == reset_hash).one()
30
+ return True
31
+ except NoResultFound:
32
+ pass
33
+ return False
34
+
35
+
36
+ def change_email_hash(info, request):
37
+ """
38
+ Check whether change email hash is correct.
39
+
40
+ :param dict info: pyramid info dict with path fragments and info
41
+ :param pyramid.request.Request request: request object
42
+
43
+ :returns: whether change email hash exists or not
44
+ :rtype: bool
45
+
46
+ """
47
+ change_email_hash = info['match'].get('hash', None)
48
+ if change_email_hash:
49
+ try:
50
+ info['match']['user'] = pyramid_basemodel.Session.query(User).filter(User.email_change_key == change_email_hash).one()
51
+ return True
52
+ except NoResultFound:
53
+ pass
54
+ return False
55
+
56
+
57
+ class CSRFCheckPredicate(CheckCSRFTokenPredicate):
58
+
59
+ """
60
+ Run csrf check dependant on configuration.
61
+
62
+ .. note::
63
+
64
+ Raises HTTPUnauthorized exception if check fails.
65
+
66
+ :raises: pyramid.httpexceptions.HTTPUnauthorized
67
+
68
+ :returns: True if check succeeds or turned off.
69
+ :rtype: bool
70
+
71
+ """
72
+
73
+ def __call__(self, context, request):
74
+ """
75
+ Run predicate check.
76
+
77
+ :param context:
78
+ :param pyramid.request.Request request:
79
+
80
+ """
81
+ if request.registry['config'].fullauth.check_csrf:
82
+ result = CheckCSRFTokenPredicate.__call__(self, context, request)
83
+ if not result:
84
+ raise HTTPUnauthorized
85
+
86
+ return True
Binary file
@@ -0,0 +1,66 @@
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
+ """Additional tools used in pyramid_fullauth."""
6
+
7
+ import string
8
+ from random import choice
9
+ from pyramid_fullauth.exceptions import (
10
+ EmptyError, ShortPasswordError, PasswordConfirmMismatchError
11
+ )
12
+
13
+
14
+ def password_generator(length, chars=(string.letters + string.digits + string.punctuation)):
15
+ """
16
+ Generate random password.
17
+
18
+ .. warning::
19
+
20
+ TODO: tests!
21
+
22
+ :param int length: length of a password to Generates
23
+ :param list chars: list of characters from which to choose
24
+ :returns: password
25
+ :rtype: str
26
+ """
27
+ return u''.join([choice(chars) for i in range(length)])
28
+
29
+
30
+ def validate_passsword(request, password, user=None):
31
+ """
32
+ Validate password properly.
33
+
34
+ .. note::
35
+
36
+ If no user provided, password is just validated
37
+
38
+ :param pyramid.request.Request request: request object
39
+ :param str password: password to be set
40
+ :param pyramid_fullauth.models.User user: user object
41
+
42
+ :raises: pyramid_fullauth.exceptions.ValidateError
43
+ """
44
+ password_config = request.registry['config'].fullauth.register.password
45
+ if not password:
46
+ raise EmptyError(
47
+ request._('Please enter your password',
48
+ domain='pyramid_fullauth'))
49
+
50
+ if password_config['length_min'] and\
51
+ len(password) < password_config['length_min']:
52
+ raise ShortPasswordError(
53
+ request._('Password is too short',
54
+ domain='pyramid_fullauth'))
55
+
56
+ # here if password doesn't match
57
+ if password_config['confirm']:
58
+ confirm_password = request.POST.get('confirm_password', u'')
59
+ if password != confirm_password:
60
+ raise PasswordConfirmMismatchError(
61
+ request._('password-mismatch',
62
+ default='Passwords don\'t match',
63
+ domain='pyramid_fullauth'))
64
+
65
+ if user:
66
+ user.password = password
Binary file
@@ -0,0 +1,15 @@
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
+ """Views submodule."""
6
+
7
+
8
+ class BaseView(object):
9
+
10
+ """basic view class."""
11
+
12
+ def __init__(self, request):
13
+ """Common init for views."""
14
+ self.request = request
15
+ self.config = request.registry['config'].fullauth
Binary file
@@ -0,0 +1,5 @@
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
+ """Basic views."""
@@ -0,0 +1,44 @@
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
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
16
+ from pyramid_fullauth.events import AfterActivate
17
+
18
+
19
+ @view_config(route_name='register:activate', permission=NO_PERMISSION_REQUIRED,
20
+ renderer="pyramid_fullauth:resources/templates/activate.mako")
21
+ class ActivateView(BaseView):
22
+
23
+ """Activate account views."""
24
+
25
+ def __call__(self):
26
+ """Process account activation."""
27
+ activate_hash = self.request.matchdict.get('hash')
28
+ user = None
29
+ response = {}
30
+ response['status'] = True
31
+ if activate_hash:
32
+ try:
33
+ user = pyramid_basemodel.Session.query(User).filter(User.activate_key == activate_hash).one()
34
+ if not user.is_active:
35
+ user.is_active = True
36
+ except NoResultFound:
37
+ response['status'] = False
38
+ try:
39
+ self.request.registry.notify(AfterActivate(self.request, user))
40
+ except HTTPFound as e:
41
+ # it's a redirect, let's follow it!
42
+ return e
43
+
44
+ return response
@@ -0,0 +1,47 @@
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
+ """Forbidden views."""
6
+
7
+ from pyramid.view import forbidden_view_config
8
+ from pyramid.security import authenticated_userid
9
+ from pyramid.httpexceptions import HTTPFound
10
+
11
+ from pyramid_fullauth.views import BaseView
12
+
13
+
14
+ class ForbiddenViews(BaseView):
15
+
16
+ """Forbidden related views."""
17
+
18
+ def __init__(self, request):
19
+ """Set all responses status to 403 by default."""
20
+ super(ForbiddenViews, self).__init__(request)
21
+ self.request.response.status_code = 403
22
+
23
+ @forbidden_view_config(renderer='pyramid_fullauth:resources/templates/403.mako')
24
+ def forbidden(self):
25
+ """Forbidden page view."""
26
+ # do not allow a user to login if they are already logged in
27
+ if authenticated_userid(self.request):
28
+ return {}
29
+
30
+ loc = self.request.route_path('login', _query=(('after', self.request.path),))
31
+ return HTTPFound(location=loc)
32
+
33
+ @forbidden_view_config(xhr=True, renderer='json')
34
+ def forbidden_json(self):
35
+ """Forbidden xhr response."""
36
+ # do not allow a user to login if they are already logged in
37
+ if authenticated_userid(self.request):
38
+ return {'status': False, 'msg':
39
+ self.request._('forbidden-notallowed',
40
+ default='You are not allowed to use this function',
41
+ domain='pyramid_fullauth')}
42
+
43
+ return {'status': False,
44
+ 'msg': self.request._('forbidden-login',
45
+ default='You have to be logged in to use this function',
46
+ domain='pyramid_fullauth'),
47
+ 'login_url': self.request.route_path('login')}
@@ -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
+ """Authorisation related views."""
6
+
7
+ from pyramid.view import view_config
8
+ from pyramid.view import view_defaults
9
+ from pyramid.httpexceptions import HTTPFound
10
+ from pyramid.security import authenticated_userid
11
+ from pyramid.security import NO_PERMISSION_REQUIRED
12
+
13
+ from sqlalchemy.orm.exc import NoResultFound
14
+ import pyramid_basemodel
15
+
16
+ from pyramid_fullauth.views import BaseView
17
+ from pyramid_fullauth.models import User
18
+ from pyramid_fullauth.events import BeforeLogIn
19
+ from pyramid_fullauth.events import AfterLogIn
20
+ from pyramid_fullauth.events import AlreadyLoggedIn
21
+
22
+
23
+ @view_defaults(route_name='login', permission=NO_PERMISSION_REQUIRED,
24
+ renderer='pyramid_fullauth:resources/templates/login.mako')
25
+ class BaseLoginView(BaseView):
26
+
27
+ """Basic logic for login views."""
28
+
29
+ def __init__(self, request):
30
+ """Prepare login views."""
31
+ super(BaseLoginView, self).__init__(request)
32
+
33
+ self.response = {
34
+ 'status': False,
35
+ 'msg': self.request._('Login error', domain='pyramid_fullauth'),
36
+ 'after': self.request.params.get(
37
+ 'after', self.request.referer or '/'),
38
+ 'csrf_token': self.request.session.get_csrf_token()
39
+ }
40
+
41
+ def _redirect_authenticated_user(self):
42
+ """Redirect already logged in user away from login page."""
43
+ redirect = HTTPFound(location=self.response['after'])
44
+ try:
45
+ self.request.registry.notify(AlreadyLoggedIn(self.request))
46
+ except HTTPFound as redirect:
47
+ pass
48
+
49
+ if self.request.is_xhr:
50
+ self.response['status'] = True
51
+ self.response['msg'] = self.request._(
52
+ 'Already logged in!',
53
+ domain='pyramid_fullauth')
54
+ self.response['after'] = redirect.location
55
+ return self.response
56
+ else:
57
+ return redirect
58
+
59
+
60
+ @view_config(request_method='GET')
61
+ class LoginView(BaseLoginView):
62
+
63
+ """Login view."""
64
+
65
+ def __call__(self):
66
+ """Display login page."""
67
+ if authenticated_userid(self.request):
68
+ return self._redirect_authenticated_user()
69
+
70
+ self.request.registry.notify(BeforeLogIn(self.request, None))
71
+
72
+ self.response['status'] = True
73
+ del self.response['msg']
74
+ return self.response
75
+
76
+
77
+ @view_config(request_method='POST', check_csrf=True)
78
+ @view_config(request_method='POST', check_csrf=True, xhr=True, renderer="json")
79
+ class LoginViewPost(BaseLoginView):
80
+
81
+ """Login view POST method."""
82
+
83
+ def __call__(self):
84
+ """Login action."""
85
+ if authenticated_userid(self.request):
86
+ return self._redirect_authenticated_user()
87
+
88
+ email = self.request.POST.get('email', '')
89
+ password = self.request.POST.get('password', '')
90
+ try:
91
+ user = pyramid_basemodel.Session.query(User).filter(User.email == email).one()
92
+ except NoResultFound:
93
+ self.request.registry.notify(BeforeLogIn(self.request, None))
94
+
95
+ self.response['msg'] = self.request._('Wrong e-mail or password.',
96
+ domain='pyramid_fullauth')
97
+ return self.response
98
+
99
+ try:
100
+ self.request.registry.notify(BeforeLogIn(self.request, user))
101
+ except AttributeError as e:
102
+ self.response['msg'] = str(e)
103
+ return self.response
104
+
105
+ if user.check_password(password):
106
+
107
+ login_kwargs = {'remember_me': self.request.POST.get('remember')}
108
+ try:
109
+ # if remember in POST set cookie timeout to one month
110
+ self.request.registry.notify(AfterLogIn(self.request, user))
111
+ except AttributeError as e:
112
+ self.response['msg'] = str(e)
113
+ return self.response
114
+ except HTTPFound as redirect:
115
+ login_kwargs['location'] = redirect.location
116
+
117
+ redirect = self.request.login_perform(user, **login_kwargs)
118
+ if self.request.is_xhr:
119
+ self.response['status'] = True
120
+ del self.response['msg']
121
+ self.response['after'] = redirect.location
122
+ return self.response
123
+ else:
124
+ return redirect
125
+ else:
126
+ self.response['msg'] = self.request._('Wrong e-mail or password.',
127
+ domain='pyramid_fullauth')
128
+ return self.response
Binary file
@@ -0,0 +1,28 @@
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
+ """De-authentication related view."""
6
+
7
+ from pyramid.view import view_config
8
+ from pyramid.httpexceptions import HTTPFound
9
+ from pyramid.security import NO_PERMISSION_REQUIRED
10
+
11
+ from pyramid_fullauth.views import BaseView
12
+
13
+
14
+ @view_config(route_name='logout', permission=NO_PERMISSION_REQUIRED)
15
+ class LogoutView(BaseView):
16
+
17
+ """Logout view."""
18
+
19
+ def __call__(self):
20
+ """Logout action."""
21
+ location = '/'
22
+ if self.config.redirects.logout:
23
+ location = self.request.route_path(self.config.redirects.logout)
24
+ # forget headers
25
+ self.request.logout()
26
+
27
+ return HTTPFound(location=location,
28
+ headers=self.request.response.headers)
Binary file
@@ -0,0 +1,5 @@
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
+ """Groups profile views."""
@@ -0,0 +1,107 @@
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
+ """Email 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
16
+
17
+ from pyramid_fullauth.events import BeforeEmailChange
18
+ from pyramid_fullauth.events import AfterEmailChange
19
+ from pyramid_fullauth.events import AfterEmailChangeActivation
20
+ from pyramid_fullauth.exceptions import EmptyError, EmailValidationError
21
+
22
+
23
+ @view_defaults(route_name='email:change', permission='email_change',
24
+ renderer='pyramid_fullauth:resources/templates/email_change.mako')
25
+ class EmailChangeViews(BaseView):
26
+
27
+ """Email change related views."""
28
+
29
+ @view_config(request_method='GET')
30
+ def get(self):
31
+ """Display email change request form."""
32
+ return {'status': True, 'csrf_token': self.request.session.get_csrf_token()}
33
+
34
+ @view_config(request_method='POST', check_csrf='csrf_token')
35
+ @view_config(request_method='POST', check_csrf='csrf_token', xhr=True, renderer="json")
36
+ def post(self):
37
+ """Process email change request."""
38
+ csrf_token = self.request.session.get_csrf_token()
39
+ try:
40
+ pyramid_basemodel.Session.query(User).filter(
41
+ User.email == self.request.POST.get('email', '')
42
+ ).one()
43
+ return {'status': False,
44
+ 'msg': self.request._('User with this email exists',
45
+ domain='pyramid_fullauth'),
46
+ 'csrf_token': csrf_token}
47
+ except NoResultFound:
48
+ pass
49
+
50
+ user = self.request.user
51
+ try:
52
+ self.request.registry.notify(BeforeEmailChange(self.request, user))
53
+ except AttributeError as e:
54
+ return {'status': False, 'msg': e.message, 'csrf_token': csrf_token}
55
+
56
+ try:
57
+ user.set_new_email(self.request.POST.get('email', ''))
58
+ except EmptyError:
59
+ return {'status': False,
60
+ 'msg': self.request._(
61
+ 'E-mail is empty',
62
+ domain='pyramid_fullauth'),
63
+ 'csrf_token': csrf_token}
64
+ except EmailValidationError:
65
+ return {'status': False,
66
+ 'msg': self.request._(
67
+ 'Incorrect e-mail format',
68
+ domain='pyramid_fullauth'),
69
+ 'csrf_token': csrf_token}
70
+
71
+ response_values = {
72
+ 'status': True,
73
+ 'msg': self.request._('We sent you email to activate your new email address',
74
+ domain='pyramid_fullauth')
75
+ }
76
+
77
+ try:
78
+ self.request.registry.notify(AfterEmailChange(self.request, user))
79
+ except HTTPFound as redirect:
80
+ if self.request.is_xhr:
81
+ response_values['url'] = redirect.location
82
+ return response_values
83
+ else:
84
+ return redirect
85
+ else:
86
+ if self.request.is_xhr:
87
+ return response_values
88
+ else:
89
+ return HTTPFound(location='/')
90
+
91
+
92
+ @view_config(route_name='email:change:continue', permission=NO_PERMISSION_REQUIRED,
93
+ renderer='pyramid_fullauth:resources/templates/email_change.mako')
94
+ class EmailChangeAccept(BaseView):
95
+
96
+ """Display email change success."""
97
+
98
+ def __call__(self):
99
+ """View that changes user email."""
100
+ user = self.request.matchdict.get('user')
101
+ user.change_email()
102
+
103
+ try:
104
+ self.request.registry.notify(AfterEmailChangeActivation(self.request, user))
105
+ except HTTPFound as redirect:
106
+ return redirect
107
+ return HTTPFound(location='/')