Mercurial > kallithea
comparison rhodecode/controllers/login.py @ 4116:ffd45b185016 rhodecode-2.2.5-gpl
Imported some of the GPLv3'd changes from RhodeCode v2.2.5.
This imports changes between changesets 21af6c4eab3d and 6177597791c2 in
RhodeCode's original repository, including only changes to Python files and HTML.
RhodeCode clearly licensed its changes to these files under GPLv3
in their /LICENSE file, which states the following:
The Python code and integrated HTML are licensed under the GPLv3 license.
(See:
https://code.rhodecode.com/rhodecode/files/v2.2.5/LICENSE
or
http://web.archive.org/web/20140512193334/https://code.rhodecode.com/rhodecode/files/f3b123159901f15426d18e3dc395e8369f70ebe0/LICENSE
for an online copy of that LICENSE file)
Conservancy reviewed these changes and confirmed that they can be licensed as
a whole to the Kallithea project under GPLv3-only.
While some of the contents committed herein are clearly licensed
GPLv3-or-later, on the whole we must assume the are GPLv3-only, since the
statement above from RhodeCode indicates that they intend GPLv3-only as their
license, per GPLv3ยง14 and other relevant sections of GPLv3.
author | Bradley M. Kuhn <bkuhn@sfconservancy.org> |
---|---|
date | Wed, 02 Jul 2014 19:03:13 -0400 |
parents | b59568e929ef |
children | 7e5f8c12a3fc |
comparison
equal
deleted
inserted
replaced
4115:8b7294a804a0 | 4116:ffd45b185016 |
---|---|
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """ | |
3 rhodecode.controllers.login | |
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
5 | |
6 Login controller for rhodeocode | |
7 | |
8 :created_on: Apr 22, 2010 | |
9 :author: marcink | |
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> | |
11 :license: GPLv3, see COPYING for more details. | |
12 """ | |
13 # This program is free software: you can redistribute it and/or modify | 2 # This program is free software: you can redistribute it and/or modify |
14 # it under the terms of the GNU General Public License as published by | 3 # it under the terms of the GNU General Public License as published by |
15 # the Free Software Foundation, either version 3 of the License, or | 4 # the Free Software Foundation, either version 3 of the License, or |
16 # (at your option) any later version. | 5 # (at your option) any later version. |
17 # | 6 # |
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 # GNU General Public License for more details. | 10 # GNU General Public License for more details. |
22 # | 11 # |
23 # You should have received a copy of the GNU General Public License | 12 # You should have received a copy of the GNU General Public License |
24 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 13 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
14 """ | |
15 rhodecode.controllers.login | |
16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 | |
18 Login controller for rhodeocode | |
19 | |
20 :created_on: Apr 22, 2010 | |
21 :author: marcink | |
22 :copyright: (c) 2013 RhodeCode GmbH. | |
23 :license: GPLv3, see LICENSE for more details. | |
24 """ | |
25 | |
25 | 26 |
26 import logging | 27 import logging |
27 import formencode | 28 import formencode |
28 import datetime | 29 import datetime |
29 import urlparse | 30 import urlparse |
30 | 31 |
31 from formencode import htmlfill | 32 from formencode import htmlfill |
32 from webob.exc import HTTPFound | 33 from webob.exc import HTTPFound |
33 from pylons.i18n.translation import _ | 34 from pylons.i18n.translation import _ |
34 from pylons.controllers.util import abort, redirect | 35 from pylons.controllers.util import redirect |
35 from pylons import request, response, session, tmpl_context as c, url | 36 from pylons import request, session, tmpl_context as c, url |
36 | 37 |
37 import rhodecode.lib.helpers as h | 38 import rhodecode.lib.helpers as h |
38 from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator | 39 from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator |
40 from rhodecode.lib.auth_modules import importplugin | |
39 from rhodecode.lib.base import BaseController, render | 41 from rhodecode.lib.base import BaseController, render |
40 from rhodecode.lib.exceptions import UserCreationError | 42 from rhodecode.lib.exceptions import UserCreationError |
41 from rhodecode.model.db import User | 43 from rhodecode.model.db import User, RhodeCodeSetting |
42 from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm | 44 from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm |
43 from rhodecode.model.user import UserModel | 45 from rhodecode.model.user import UserModel |
44 from rhodecode.model.meta import Session | 46 from rhodecode.model.meta import Session |
45 | 47 |
46 | 48 |
50 class LoginController(BaseController): | 52 class LoginController(BaseController): |
51 | 53 |
52 def __before__(self): | 54 def __before__(self): |
53 super(LoginController, self).__before__() | 55 super(LoginController, self).__before__() |
54 | 56 |
57 def _store_user_in_session(self, username, remember=False): | |
58 user = User.get_by_username(username, case_insensitive=True) | |
59 auth_user = AuthUser(user.user_id) | |
60 auth_user.set_authenticated() | |
61 cs = auth_user.get_cookie_store() | |
62 session['rhodecode_user'] = cs | |
63 user.update_lastlogin() | |
64 Session().commit() | |
65 | |
66 # If they want to be remembered, update the cookie | |
67 if remember: | |
68 _year = (datetime.datetime.now() + | |
69 datetime.timedelta(seconds=60 * 60 * 24 * 365)) | |
70 session._set_cookie_expires(_year) | |
71 | |
72 session.save() | |
73 | |
74 log.info('user %s is now authenticated and stored in ' | |
75 'session, session attrs %s' % (username, cs)) | |
76 | |
77 # dumps session attrs back to cookie | |
78 session._update_cookie_out() | |
79 # we set new cookie | |
80 headers = None | |
81 if session.request['set_cookie']: | |
82 # send set-cookie headers back to response to update cookie | |
83 headers = [('Set-Cookie', session.request['cookie_out'])] | |
84 return headers | |
85 | |
86 def _validate_came_from(self, came_from): | |
87 if not came_from: | |
88 return came_from | |
89 | |
90 parsed = urlparse.urlparse(came_from) | |
91 server_parsed = urlparse.urlparse(url.current()) | |
92 allowed_schemes = ['http', 'https'] | |
93 if parsed.scheme and parsed.scheme not in allowed_schemes: | |
94 log.error('Suspicious URL scheme detected %s for url %s' % | |
95 (parsed.scheme, parsed)) | |
96 came_from = url('home') | |
97 elif server_parsed.netloc != parsed.netloc: | |
98 log.error('Suspicious NETLOC detected %s for url %s server url ' | |
99 'is: %s' % (parsed.netloc, parsed, server_parsed)) | |
100 came_from = url('home') | |
101 return came_from | |
102 | |
55 def index(self): | 103 def index(self): |
104 _default_came_from = url('home') | |
105 came_from = self._validate_came_from(request.GET.get('came_from')) | |
106 c.came_from = came_from or _default_came_from | |
107 | |
108 not_default = self.rhodecode_user.username != User.DEFAULT_USER | |
109 ip_allowed = self.rhodecode_user.ip_allowed | |
110 | |
56 # redirect if already logged in | 111 # redirect if already logged in |
57 c.came_from = request.GET.get('came_from') | |
58 not_default = self.rhodecode_user.username != 'default' | |
59 ip_allowed = self.rhodecode_user.ip_allowed | |
60 if self.rhodecode_user.is_authenticated and not_default and ip_allowed: | 112 if self.rhodecode_user.is_authenticated and not_default and ip_allowed: |
61 return redirect(url('home')) | 113 raise HTTPFound(location=c.came_from) |
62 | 114 |
63 if request.POST: | 115 if request.POST: |
64 # import Login Form validator class | 116 # import Login Form validator class |
65 login_form = LoginForm() | 117 login_form = LoginForm() |
66 try: | 118 try: |
67 session.invalidate() | 119 session.invalidate() |
68 c.form_result = login_form.to_python(dict(request.POST)) | 120 c.form_result = login_form.to_python(dict(request.POST)) |
69 # form checks for username/password, now we're authenticated | 121 # form checks for username/password, now we're authenticated |
70 username = c.form_result['username'] | 122 headers = self._store_user_in_session( |
71 user = User.get_by_username(username, case_insensitive=True) | 123 username=c.form_result['username'], |
72 auth_user = AuthUser(user.user_id) | 124 remember=c.form_result['remember']) |
73 auth_user.set_authenticated() | 125 raise HTTPFound(location=c.came_from, headers=headers) |
74 cs = auth_user.get_cookie_store() | |
75 session['rhodecode_user'] = cs | |
76 user.update_lastlogin() | |
77 Session().commit() | |
78 | |
79 # If they want to be remembered, update the cookie | |
80 if c.form_result['remember']: | |
81 _year = (datetime.datetime.now() + | |
82 datetime.timedelta(seconds=60 * 60 * 24 * 365)) | |
83 session._set_cookie_expires(_year) | |
84 | |
85 session.save() | |
86 | |
87 log.info('user %s is now authenticated and stored in ' | |
88 'session, session attrs %s' % (username, cs)) | |
89 | |
90 # dumps session attrs back to cookie | |
91 session._update_cookie_out() | |
92 | |
93 # we set new cookie | |
94 headers = None | |
95 if session.request['set_cookie']: | |
96 # send set-cookie headers back to response to update cookie | |
97 headers = [('Set-Cookie', session.request['cookie_out'])] | |
98 | |
99 allowed_schemes = ['http', 'https'] | |
100 if c.came_from: | |
101 parsed = urlparse.urlparse(c.came_from) | |
102 server_parsed = urlparse.urlparse(url.current()) | |
103 if parsed.scheme and parsed.scheme not in allowed_schemes: | |
104 log.error( | |
105 'Suspicious URL scheme detected %s for url %s' % | |
106 (parsed.scheme, parsed)) | |
107 c.came_from = url('home') | |
108 elif server_parsed.netloc != parsed.netloc: | |
109 log.error('Suspicious NETLOC detected %s for url %s' | |
110 'server url is: %s' % | |
111 (parsed.netloc, parsed, server_parsed)) | |
112 c.came_from = url('home') | |
113 raise HTTPFound(location=c.came_from, headers=headers) | |
114 else: | |
115 raise HTTPFound(location=url('home'), headers=headers) | |
116 | |
117 except formencode.Invalid, errors: | 126 except formencode.Invalid, errors: |
118 defaults = errors.value | 127 defaults = errors.value |
119 # remove password from filling in form again | 128 # remove password from filling in form again |
120 del defaults['password'] | 129 del defaults['password'] |
121 return htmlfill.render( | 130 return htmlfill.render( |
129 # the fly can throw this exception signaling that there's issue | 138 # the fly can throw this exception signaling that there's issue |
130 # with user creation, explanation should be provided in | 139 # with user creation, explanation should be provided in |
131 # Exception itself | 140 # Exception itself |
132 h.flash(e, 'error') | 141 h.flash(e, 'error') |
133 | 142 |
143 # check if we use container plugin, and try to login using it. | |
144 auth_plugins = RhodeCodeSetting.get_auth_plugins() | |
145 if any((importplugin(name).is_container_auth for name in auth_plugins)): | |
146 from rhodecode.lib import auth_modules | |
147 try: | |
148 auth_info = auth_modules.authenticate('', '', request.environ) | |
149 except UserCreationError, e: | |
150 log.error(e) | |
151 h.flash(e, 'error') | |
152 # render login, with flash message about limit | |
153 return render('/login.html') | |
154 | |
155 if auth_info: | |
156 headers = self._store_user_in_session(auth_info.get('username')) | |
157 raise HTTPFound(location=c.came_from, headers=headers) | |
134 return render('/login.html') | 158 return render('/login.html') |
135 | 159 |
136 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', | 160 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', |
137 'hg.register.manual_activate') | 161 'hg.register.manual_activate') |
138 def register(self): | 162 def register(self): |
139 c.auto_active = 'hg.register.auto_activate' in User.get_default_user()\ | 163 c.auto_active = 'hg.register.auto_activate' in User.get_default_user()\ |
140 .AuthUser.permissions['global'] | 164 .AuthUser.permissions['global'] |
141 | 165 |
166 settings = RhodeCodeSetting.get_app_settings() | |
167 captcha_private_key = settings.get('rhodecode_captcha_private_key') | |
168 c.captcha_active = bool(captcha_private_key) | |
169 c.captcha_public_key = settings.get('rhodecode_captcha_public_key') | |
170 | |
142 if request.POST: | 171 if request.POST: |
143 register_form = RegisterForm()() | 172 register_form = RegisterForm()() |
144 try: | 173 try: |
145 form_result = register_form.to_python(dict(request.POST)) | 174 form_result = register_form.to_python(dict(request.POST)) |
146 form_result['active'] = c.auto_active | 175 form_result['active'] = c.auto_active |
176 | |
177 if c.captcha_active: | |
178 from rhodecode.lib.recaptcha import submit | |
179 response = submit(request.POST.get('recaptcha_challenge_field'), | |
180 request.POST.get('recaptcha_response_field'), | |
181 private_key=captcha_private_key, | |
182 remoteip=self.ip_addr) | |
183 if c.captcha_active and not response.is_valid: | |
184 _value = form_result | |
185 _msg = _('bad captcha') | |
186 error_dict = {'recaptcha_field': _msg} | |
187 raise formencode.Invalid(_msg, _value, None, | |
188 error_dict=error_dict) | |
189 | |
147 UserModel().create_registration(form_result) | 190 UserModel().create_registration(form_result) |
148 h.flash(_('You have successfully registered into RhodeCode'), | 191 h.flash(_('You have successfully registered into RhodeCode'), |
149 category='success') | 192 category='success') |
150 Session().commit() | 193 Session().commit() |
151 return redirect(url('login_home')) | 194 return redirect(url('login_home')) |
152 | 195 |
153 except formencode.Invalid, errors: | 196 except formencode.Invalid, errors: |
154 return htmlfill.render( | 197 return htmlfill.render( |
165 h.flash(e, 'error') | 208 h.flash(e, 'error') |
166 | 209 |
167 return render('/register.html') | 210 return render('/register.html') |
168 | 211 |
169 def password_reset(self): | 212 def password_reset(self): |
213 settings = RhodeCodeSetting.get_app_settings() | |
214 captcha_private_key = settings.get('rhodecode_captcha_private_key') | |
215 c.captcha_active = bool(captcha_private_key) | |
216 c.captcha_public_key = settings.get('rhodecode_captcha_public_key') | |
217 | |
170 if request.POST: | 218 if request.POST: |
171 password_reset_form = PasswordResetForm()() | 219 password_reset_form = PasswordResetForm()() |
172 try: | 220 try: |
173 form_result = password_reset_form.to_python(dict(request.POST)) | 221 form_result = password_reset_form.to_python(dict(request.POST)) |
222 if c.captcha_active: | |
223 from rhodecode.lib.recaptcha import submit | |
224 response = submit(request.POST.get('recaptcha_challenge_field'), | |
225 request.POST.get('recaptcha_response_field'), | |
226 private_key=captcha_private_key, | |
227 remoteip=self.ip_addr) | |
228 if c.captcha_active and not response.is_valid: | |
229 _value = form_result | |
230 _msg = _('bad captcha') | |
231 error_dict = {'recaptcha_field': _msg} | |
232 raise formencode.Invalid(_msg, _value, None, | |
233 error_dict=error_dict) | |
174 UserModel().reset_password_link(form_result) | 234 UserModel().reset_password_link(form_result) |
175 h.flash(_('Your password reset link was sent'), | 235 h.flash(_('Your password reset link was sent'), |
176 category='success') | 236 category='success') |
177 return redirect(url('login_home')) | 237 return redirect(url('login_home')) |
178 | 238 |