##// END OF EJS Templates
login: Remove social auth fragments from register views.
johbo -
r38:2451deb0 default
parent child Browse files
Show More
@@ -1,369 +1,351 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import datetime
22 22 import formencode
23 23 import logging
24 24 import urlparse
25 25 import uuid
26 26
27 27 from pylons import url
28 28 from pyramid.httpexceptions import HTTPFound
29 29 from pyramid.i18n import TranslationStringFactory
30 30 from pyramid.view import view_config
31 31 from recaptcha.client.captcha import submit
32 32
33 33 from rhodecode.authentication.base import loadplugin
34 34 from rhodecode.lib.auth import (
35 35 AuthUser, HasPermissionAnyDecorator, CSRFRequired)
36 36 from rhodecode.lib.base import get_ip_addr
37 37 from rhodecode.lib.exceptions import UserCreationError
38 38 from rhodecode.lib.utils2 import safe_str
39 39 from rhodecode.model.db import User
40 40 from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm
41 41 from rhodecode.model.login_session import LoginSession
42 42 from rhodecode.model.meta import Session
43 43 from rhodecode.model.settings import SettingsModel
44 44 from rhodecode.model.user import UserModel
45 45
46 46
47 47 _ = TranslationStringFactory('rhodecode-enterprise')
48 48
49 49 log = logging.getLogger(__name__)
50 50
51 51
52 52 def _store_user_in_session(session, username, remember=False):
53 53 user = User.get_by_username(username, case_insensitive=True)
54 54 auth_user = AuthUser(user.user_id)
55 55 auth_user.set_authenticated()
56 56 cs = auth_user.get_cookie_store()
57 57 session['rhodecode_user'] = cs
58 58 user.update_lastlogin()
59 59 Session().commit()
60 60
61 61 # If they want to be remembered, update the cookie
62 62 if remember:
63 63 _year = (datetime.datetime.now() +
64 64 datetime.timedelta(seconds=60 * 60 * 24 * 365))
65 65 session._set_cookie_expires(_year)
66 66
67 67 session.save()
68 68
69 69 log.info('user %s is now authenticated and stored in '
70 70 'session, session attrs %s', username, cs)
71 71
72 72 # dumps session attrs back to cookie
73 73 session._update_cookie_out()
74 74 # we set new cookie
75 75 headers = None
76 76 if session.request['set_cookie']:
77 77 # send set-cookie headers back to response to update cookie
78 78 headers = [('Set-Cookie', session.request['cookie_out'])]
79 79 return headers
80 80
81 81
82 82 class LoginView(object):
83 83
84 84 def __init__(self, context, request):
85 85 self.request = request
86 86 self.context = context
87 87 self.session = request.session
88 88 self._rhodecode_user = request.user
89 89
90 90 def _validate_came_from(self, came_from):
91 91 if not came_from:
92 92 return came_from
93 93
94 94 parsed = urlparse.urlparse(came_from)
95 95 allowed_schemes = ['http', 'https']
96 96 if parsed.scheme and parsed.scheme not in allowed_schemes:
97 97 log.error('Suspicious URL scheme detected %s for url %s' %
98 98 (parsed.scheme, parsed))
99 99 came_from = url('home')
100 100 elif parsed.netloc and self.request.host != parsed.netloc:
101 101 log.error('Suspicious NETLOC detected %s for url %s server url '
102 102 'is: %s' % (parsed.netloc, parsed, self.request.host))
103 103 came_from = url('home')
104 104 if any(bad_str in parsed.path for bad_str in ('\r', '\n')):
105 105 log.error('Header injection detected `%s` for url %s server url ' %
106 106 (parsed.path, parsed))
107 107 came_from = url('home')
108 108 return came_from
109 109
110 110 def _get_came_from(self):
111 111 _default_came_from = url('home')
112 112 came_from = self._validate_came_from(
113 113 safe_str(self.request.GET.get('came_from', '')))
114 114 return came_from or _default_came_from
115 115
116 116 def _get_template_context(self):
117 117 return {
118 118 'came_from': self._get_came_from(),
119 119 'defaults': {},
120 120 'errors': {},
121 121 }
122 122
123 123 @view_config(
124 124 route_name='login', request_method='GET',
125 125 renderer='rhodecode:templates/login.html')
126 126 def login(self):
127 127 user = self.request.user
128 128
129 129 # redirect if already logged in
130 130 if user.is_authenticated and not user.is_default and user.ip_allowed:
131 131 raise HTTPFound(self._get_came_from())
132 132
133 133 return self._get_template_context()
134 134
135 135 @view_config(
136 136 route_name='login', request_method='POST',
137 137 renderer='rhodecode:templates/login.html')
138 138 def login_post(self):
139 139 came_from = self._get_came_from()
140 140 session = self.request.session
141 141 login_form = LoginForm()()
142 142
143 143 try:
144 144 session.invalidate()
145 145 form_result = login_form.to_python(self.request.params)
146 146 # form checks for username/password, now we're authenticated
147 147 headers = _store_user_in_session(
148 148 self.session,
149 149 username=form_result['username'],
150 150 remember=form_result['remember'])
151 151 raise HTTPFound(came_from, headers=headers)
152 152 except formencode.Invalid as errors:
153 153 defaults = errors.value
154 154 # remove password from filling in form again
155 155 del defaults['password']
156 156 render_ctx = self._get_template_context()
157 157 render_ctx.update({
158 158 'errors': errors.error_dict,
159 159 'defaults': defaults,
160 160 })
161 161 return render_ctx
162 162
163 163 except UserCreationError as e:
164 164 # container auth or other auth functions that create users on
165 165 # the fly can throw this exception signaling that there's issue
166 166 # with user creation, explanation should be provided in
167 167 # Exception itself
168 168 session.flash(e, queue='error')
169 169
170 170 # check if we use container plugin, and try to login using it.
171 171 from rhodecode.authentication.base import authenticate, HTTP_TYPE
172 172 try:
173 173 log.debug('Running PRE-AUTH for container based authentication')
174 174 auth_info = authenticate(
175 175 '', '', self.request.environ, HTTP_TYPE, skip_missing=True)
176 176 except UserCreationError as e:
177 177 log.error(e)
178 178 session.flash(e, queue='error')
179 179 # render login, with flash message about limit
180 180 return self._get_template_context()
181 181
182 182 if auth_info:
183 183 headers = _store_user_in_session(auth_info.get('username'))
184 184 raise HTTPFound(came_from, headers=headers)
185 185
186 186 return self._get_template_context()
187 187
188 188 @CSRFRequired()
189 189 @view_config(route_name='logout', request_method='POST')
190 190 def logout(self):
191 191 LoginSession().destroy_user_session()
192 192 return HTTPFound(url('home'))
193 193
194 194 @HasPermissionAnyDecorator(
195 195 'hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')
196 196 @view_config(
197 197 route_name='register', request_method='GET',
198 198 renderer='rhodecode:templates/register.html',)
199 199 def register(self):
200 200 settings = SettingsModel().get_all_settings()
201
202 social_data = self.session.get('rhodecode.social_auth')
203 form_defaults = {}
204 if social_data:
205 password = str(uuid.uuid4())
206 form_defaults = {
207 'username': social_data['user'].get('user_name'),
208 'password': password,
209 'password_confirmation': password,
210 'email': social_data['user'].get('email'),
211 }
212
201 captcha_public_key = settings.get('rhodecode_captcha_public_key')
202 captcha_private_key = settings.get('rhodecode_captcha_private_key')
203 captcha_active = bool(captcha_private_key)
204 register_message = settings.get('rhodecode_register_message') or ''
213 205 auto_active = 'hg.register.auto_activate' in User.get_default_user()\
214 206 .AuthUser.permissions['global']
215 captcha_private_key = settings.get('rhodecode_captcha_private_key')
207
216 208 render_ctx = self._get_template_context()
217 209 render_ctx.update({
218 210 'auto_active': auto_active,
219 'captcha_active': bool(captcha_private_key),
220 'captcha_public_key': settings.get('rhodecode_captcha_public_key'),
221 'defaults': form_defaults,
222 'register_message': settings.get('rhodecode_register_message') or '',
211 'captcha_active': captcha_active,
212 'captcha_public_key': captcha_public_key,
213 'register_message': register_message,
223 214 })
224 215 return render_ctx
225 216
226 217 @view_config(
227 218 route_name='register', request_method='POST',
228 219 renderer='rhodecode:templates/register.html')
229 220 def register_post(self):
230 social_data = self.session.get('rhodecode.social_auth')
231 221 settings = SettingsModel().get_all_settings()
232 222 captcha_private_key = settings.get('rhodecode_captcha_private_key')
233 223 captcha_active = bool(captcha_private_key)
224 register_message = settings.get('rhodecode_register_message') or ''
234 225 auto_active = 'hg.register.auto_activate' in User.get_default_user()\
235 226 .AuthUser.permissions['global']
236 register_message = settings.get('rhodecode_register_message') or ''
237 227
238 228 register_form = RegisterForm()()
239 229 try:
240 230 form_result = register_form.to_python(self.request.params)
241 231 form_result['active'] = auto_active
242 232
243 233 if captcha_active:
244 234 response = submit(
245 235 self.request.params.get('recaptcha_challenge_field'),
246 236 self.request.params.get('recaptcha_response_field'),
247 237 private_key=captcha_private_key,
248 238 remoteip=self.ip_addr)
249 239 if captcha_active and not response.is_valid:
250 240 _value = form_result
251 241 _msg = _('bad captcha')
252 242 error_dict = {'recaptcha_field': _msg}
253 243 raise formencode.Invalid(_msg, _value, None,
254 244 error_dict=error_dict)
255 245
256 new_user = UserModel().create_registration(form_result)
257 if social_data:
258 plugin_name = 'egg:rhodecode-enterprise-ee#{}'.format(
259 social_data['credentials.provider']
260 )
261 auth_plugin = loadplugin(plugin_name)
262 if auth_plugin:
263 auth_plugin.handle_social_data(
264 self.session, new_user.user_id, social_data)
246 UserModel().create_registration(form_result)
265 247 self.session.flash(
266 248 _('You have successfully registered with RhodeCode'),
267 249 queue='success')
268 250 Session().commit()
269 251
270 252 redirect_ro = self.request.route_path('login')
271 253 raise HTTPFound(redirect_ro)
272 254
273 255 except formencode.Invalid as errors:
274 256 del errors.value['password']
275 257 del errors.value['password_confirmation']
276 258 render_ctx = self._get_template_context()
277 259 render_ctx.update({
278 260 'errors': errors.error_dict,
279 261 'defaults': errors.value,
280 262 'register_message': register_message,
281 263 })
282 264 return render_ctx
283 265
284 266 except UserCreationError as e:
285 267 # container auth or other auth functions that create users on
286 268 # the fly can throw this exception signaling that there's issue
287 269 # with user creation, explanation should be provided in
288 270 # Exception itself
289 271 self.session.flash(e, queue='error')
290 272 render_ctx = self._get_template_context()
291 273 render_ctx.update({
292 274 'register_message': register_message,
293 275 })
294 276 return render_ctx
295 277
296 278 @view_config(
297 279 route_name='reset_password', request_method=('GET', 'POST'),
298 280 renderer='rhodecode:templates/password_reset.html')
299 281 def password_reset(self):
300 282 settings = SettingsModel().get_all_settings()
301 283 captcha_private_key = settings.get('rhodecode_captcha_private_key')
302 284 captcha_active = bool(captcha_private_key)
303 285 captcha_public_key = settings.get('rhodecode_captcha_public_key')
304 286
305 287 render_ctx = {
306 288 'captcha_active': captcha_active,
307 289 'captcha_public_key': captcha_public_key,
308 290 'defaults': {},
309 291 'errors': {},
310 292 }
311 293
312 294 if self.request.POST:
313 295 password_reset_form = PasswordResetForm()()
314 296 try:
315 297 form_result = password_reset_form.to_python(
316 298 self.request.params)
317 299 if captcha_active:
318 300 response = submit(
319 301 self.request.params.get('recaptcha_challenge_field'),
320 302 self.request.params.get('recaptcha_response_field'),
321 303 private_key=captcha_private_key,
322 304 remoteip=get_ip_addr(self.request.environ))
323 305 if captcha_active and not response.is_valid:
324 306 _value = form_result
325 307 _msg = _('bad captcha')
326 308 error_dict = {'recaptcha_field': _msg}
327 309 raise formencode.Invalid(_msg, _value, None,
328 310 error_dict=error_dict)
329 311
330 312 # Generate reset URL and send mail.
331 313 user_email = form_result['email']
332 314 user = User.get_by_email(user_email)
333 315 password_reset_url = self.request.route_url(
334 316 'reset_password_confirmation',
335 317 _query={'key': user.api_key})
336 318 UserModel().reset_password_link(
337 319 form_result, password_reset_url)
338 320
339 321 # Display success message and redirect.
340 322 self.session.flash(
341 323 _('Your password reset link was sent'),
342 324 queue='success')
343 325 return HTTPFound(self.request.route_path('login'))
344 326
345 327 except formencode.Invalid as errors:
346 328 render_ctx.update({
347 329 'defaults': errors.value,
348 330 'errors': errors.error_dict,
349 331 })
350 332
351 333 return render_ctx
352 334
353 335 @view_config(route_name='reset_password_confirmation',
354 336 request_method='GET')
355 337 def password_reset_confirmation(self):
356 338 if self.request.GET and self.request.GET.get('key'):
357 339 try:
358 340 user = User.get_by_auth_token(self.request.GET.get('key'))
359 341 data = {'email': user.email}
360 342 UserModel().reset_password(data)
361 343 self.session.flash(
362 344 _('Your password reset was successful, '
363 345 'a new password has been sent to your email'),
364 346 queue='success')
365 347 except Exception as e:
366 348 log.error(e)
367 349 return HTTPFound(self.request.route_path('reset_password'))
368 350
369 351 return HTTPFound(self.request.route_path('login'))
General Comments 0
You need to be logged in to leave comments. Login now