##// END OF EJS Templates
i18n: updated translation for Polish...
i18n: updated translation for Polish Currently translated at 56.5% (614 of 1087 strings)

File last commit:

r8076:e51ad2cd default
r8092:7fef5132 default
Show More
login.py
255 lines | 10.7 KiB | text/x-python | PythonLexer
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
kallithea.controllers.login
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Bradley M. Kuhn
General renaming to Kallithea
r4212 Login controller for Kallithea
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 This file was forked by the Kallithea project in July 2014.
Original author and date, and relevant copyright and licensing information is below:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :created_on: Apr 22, 2010
:author: marcink
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 :copyright: (c) 2013 RhodeCode GmbH, and others.
Bradley M. Kuhn
Correct licensing information in individual files....
r4208 :license: GPLv3, see LICENSE.md for more details.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
import logging
Søren Løvborg
login: enhance came_from validation...
r5523 import re
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import formencode
from formencode import htmlfill
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 from tg import request, session
from tg import tmpl_context as c
Mads Kiilerich
tg: minimize future diff by some mocking and replacing some pylons imports with tg...
r6508 from tg.i18n import ugettext as _
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 from webob.exc import HTTPBadRequest, HTTPFound
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
import kallithea.lib.helpers as h
Thomas De Schampheleire
Turbogears2 migration: replace pylons.url by kallithea.config.routing.url...
r6182 from kallithea.config.routing import url
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator
Søren Løvborg
log_in_user: extract user session setup from LoginController...
r5256 from kallithea.lib.base import BaseController, log_in_user, render
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 from kallithea.lib.exceptions import UserCreationError
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 from kallithea.model.db import Setting, User
from kallithea.model.forms import LoginForm, PasswordResetConfirmationForm, PasswordResetRequestForm, RegisterForm
from kallithea.model.meta import Session
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 from kallithea.model.user import UserModel
log = logging.getLogger(__name__)
class LoginController(BaseController):
Søren Løvborg
login: enhance came_from validation...
r5523 def _validate_came_from(self, came_from,
_re=re.compile(r"/(?!/)[-!#$%&'()*+,./:;=?@_~0-9A-Za-z]*$")):
"""Return True if came_from is valid and can and should be used.
Determines if a URI reference is valid and relative to the origin;
or in RFC 3986 terms, whether it matches this production:
origin-relative-ref = path-absolute [ "?" query ] [ "#" fragment ]
with the exception that '%' escapes are not validated and '#' is
allowed inside the fragment part.
"""
return _re.match(came_from) is not None
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def index(self):
Mads Kiilerich
py3: drop the last uses of safe_str - they are no longer relevant when we don't have a separate unicode type
r8076 c.came_from = request.GET.get('came_from', '')
Mads Kiilerich
login: make it clear that an invalid came_from is an invalid request
r5509 if c.came_from:
if not self._validate_came_from(c.came_from):
log.error('Invalid came_from (not server-relative): %r', c.came_from)
raise HTTPBadRequest()
Mads Kiilerich
login: inline _redirect_to_origin...
r5508 else:
Søren Løvborg
login: use server-relative URLs in came_from correctly...
r5512 c.came_from = url('home')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
if request.POST:
# import Login Form validator class
Thomas De Schampheleire
forms: wrap LoginForm inside function like other forms...
r6325 login_form = LoginForm()()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 try:
c.form_result = login_form.to_python(dict(request.POST))
# form checks for username/password, now we're authenticated
Søren Løvborg
log_in_user: extract user session setup from LoginController...
r5256 username = c.form_result['username']
Andrew Shadura
auth: allow web login with email addresses...
r5671 user = User.get_by_username_or_email(username, case_insensitive=True)
Mads Kiilerich
cleanup: consistently use 'except ... as ...:'...
r5374 except formencode.Invalid as errors:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 defaults = errors.value
# remove password from filling in form again
Mads Kiilerich
login: don't crash on login POSTs without password
r5846 defaults.pop('password', None)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return htmlfill.render(
render('/login.html'),
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
Mads Kiilerich
controllers: consistently use formfill.render with force_defaults=False...
r4941 encoding="UTF-8",
force_defaults=False)
Mads Kiilerich
cleanup: consistently use 'except ... as ...:'...
r5374 except UserCreationError as e:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # container auth or other auth functions that create users on
# the fly can throw this exception signaling that there's issue
# with user creation, explanation should be provided in
# Exception itself
h.flash(e, 'error')
Søren Løvborg
log_in_user: extract user session setup from LoginController...
r5256 else:
Mads Kiilerich
auth: move IP check to AuthUser.make - it is more about accepting authentication than about permissions after authentication
r7603 auth_user = log_in_user(user, c.form_result['remember'], is_external_auth=False, ip_addr=request.ip_addr)
Mads Kiilerich
auth: introduce AuthUser.make factory which can return None if user can't be authenticated
r7602 # TODO: handle auth_user is None as failed authentication?
Søren Løvborg
login: use server-relative URLs in came_from correctly...
r5512 raise HTTPFound(location=c.came_from)
Mads Kiilerich
auth: don't ignore login POSTs if already logged in...
r7424 else:
# redirect if already logged in
Mads Kiilerich
auth: use other and better checks than is_authenticated...
r7599 if not request.authuser.is_anonymous:
Mads Kiilerich
auth: don't ignore login POSTs if already logged in...
r7424 raise HTTPFound(location=c.came_from)
Mads Kiilerich
auth: use other and better checks than is_authenticated...
r7599 # continue to show login to default user
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
return render('/login.html')
@HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
'hg.register.manual_activate')
def register(self):
Mads Kiilerich
auth: drop confusing and layering-violating User.AuthUser property...
r7403 def_user_perms = AuthUser(dbuser=User.get_default_user()).permissions['global']
c.auto_active = 'hg.register.auto_activate' in def_user_perms
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Bradley M. Kuhn
Rename database classes (but not table names)
r4203 settings = Setting.get_app_settings()
Bradley M. Kuhn
Drop rhodecode_ prefix for known setting names that are stored in kallithea_settings without prefix
r4218 captcha_private_key = settings.get('captcha_private_key')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 c.captcha_active = bool(captcha_private_key)
Bradley M. Kuhn
Drop rhodecode_ prefix for known setting names that are stored in kallithea_settings without prefix
r4218 c.captcha_public_key = settings.get('captcha_public_key')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
if request.POST:
register_form = RegisterForm()()
try:
form_result = register_form.to_python(dict(request.POST))
form_result['active'] = c.auto_active
if c.captcha_active:
from kallithea.lib.recaptcha import submit
Patrick Vane
recaptcha: Update to Google recaptcha API v2 (Issue #313)...
r7170 response = submit(request.POST.get('g-recaptcha-response'),
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 private_key=captcha_private_key,
Mads Kiilerich
controllers: avoid setting request state in controller instances - set it in the thread global request variable...
r6412 remoteip=request.ip_addr)
Patrick Vane
recaptcha: Update to Google recaptcha API v2 (Issue #313)...
r7170 if not response.is_valid:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 _value = form_result
Mads Kiilerich
spelling: fix title casing on various translated strings...
r5127 _msg = _('Bad captcha')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 error_dict = {'recaptcha_field': _msg}
raise formencode.Invalid(_msg, _value, None,
error_dict=error_dict)
UserModel().create_registration(form_result)
Søren Løvborg
login: have self-signup confirmation message respect site_name
r6030 h.flash(_('You have successfully registered with %s') % (c.site_name or 'Kallithea'),
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 category='success')
Session().commit()
Søren Løvborg
cleanup: replace redirect with WebOb exceptions...
r5543 raise HTTPFound(location=url('login_home'))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: consistently use 'except ... as ...:'...
r5374 except formencode.Invalid as errors:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return htmlfill.render(
render('/register.html'),
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
Mads Kiilerich
controllers: consistently use formfill.render with force_defaults=False...
r4941 encoding="UTF-8",
force_defaults=False)
Mads Kiilerich
cleanup: consistently use 'except ... as ...:'...
r5374 except UserCreationError as e:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # container auth or other auth functions that create users on
# the fly can throw this exception signaling that there's issue
# with user creation, explanation should be provided in
# Exception itself
h.flash(e, 'error')
return render('/register.html')
def password_reset(self):
Bradley M. Kuhn
Rename database classes (but not table names)
r4203 settings = Setting.get_app_settings()
Bradley M. Kuhn
Drop rhodecode_ prefix for known setting names that are stored in kallithea_settings without prefix
r4218 captcha_private_key = settings.get('captcha_private_key')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 c.captcha_active = bool(captcha_private_key)
Bradley M. Kuhn
Drop rhodecode_ prefix for known setting names that are stored in kallithea_settings without prefix
r4218 c.captcha_public_key = settings.get('captcha_public_key')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
if request.POST:
Andrew Shadura
auth: secure password reset implementation...
r5457 password_reset_form = PasswordResetRequestForm()()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 try:
form_result = password_reset_form.to_python(dict(request.POST))
if c.captcha_active:
from kallithea.lib.recaptcha import submit
Patrick Vane
recaptcha: Update to Google recaptcha API v2 (Issue #313)...
r7170 response = submit(request.POST.get('g-recaptcha-response'),
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 private_key=captcha_private_key,
Mads Kiilerich
controllers: avoid setting request state in controller instances - set it in the thread global request variable...
r6412 remoteip=request.ip_addr)
Patrick Vane
recaptcha: Update to Google recaptcha API v2 (Issue #313)...
r7170 if not response.is_valid:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 _value = form_result
Mads Kiilerich
spelling: fix title casing on various translated strings...
r5127 _msg = _('Bad captcha')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 error_dict = {'recaptcha_field': _msg}
raise formencode.Invalid(_msg, _value, None,
error_dict=error_dict)
Andrew Shadura
auth: secure password reset implementation...
r5457 redirect_link = UserModel().send_reset_password_email(form_result)
h.flash(_('A password reset confirmation code has been sent'),
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 category='success')
Søren Løvborg
cleanup: replace redirect with WebOb exceptions...
r5543 raise HTTPFound(location=redirect_link)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: consistently use 'except ... as ...:'...
r5374 except formencode.Invalid as errors:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return htmlfill.render(
render('/password_reset.html'),
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
Mads Kiilerich
controllers: consistently use formfill.render with force_defaults=False...
r4941 encoding="UTF-8",
force_defaults=False)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
return render('/password_reset.html')
def password_reset_confirmation(self):
Andrew Shadura
auth: secure password reset implementation...
r5457 # This controller handles both GET and POST requests, though we
# only ever perform the actual password change on POST (since
# GET requests are not allowed to have side effects, and do not
# receive automatic CSRF protection).
# The template needs the email address outside of the form.
c.email = request.params.get('email')
Mads Kiilerich
login: fix incorrect CSRF rejection of "Reset Your Password" form (Issue #350)...
r8010 c.timestamp = request.params.get('timestamp') or ''
c.token = request.params.get('token') or ''
Andrew Shadura
auth: secure password reset implementation...
r5457 if not request.POST:
Mads Kiilerich
login: fix incorrect CSRF rejection of "Reset Your Password" form (Issue #350)...
r8010 return render('/password_reset_confirmation.html')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Andrew Shadura
auth: secure password reset implementation...
r5457 form = PasswordResetConfirmationForm()()
try:
form_result = form.to_python(dict(request.POST))
except formencode.Invalid as errors:
return htmlfill.render(
render('/password_reset_confirmation.html'),
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
encoding='UTF-8')
if not UserModel().verify_reset_password_token(
form_result['email'],
form_result['timestamp'],
form_result['token'],
):
return htmlfill.render(
render('/password_reset_confirmation.html'),
defaults=form_result,
errors={'token': _('Invalid password reset token')},
prefix_error=False,
encoding='UTF-8')
UserModel().reset_password(form_result['email'], form_result['password'])
h.flash(_('Successfully updated password'), category='success')
Søren Løvborg
cleanup: replace redirect with WebOb exceptions...
r5543 raise HTTPFound(location=url('login_home'))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def logout(self):
session.delete()
log.info('Logging out and deleting session for user')
Søren Løvborg
cleanup: replace redirect with WebOb exceptions...
r5543 raise HTTPFound(location=url('home'))
Mads Kiilerich
tests: provide _authentication_token when POSTing...
r4993
Mads Kiilerich
helpers: change CSRF protection POST parameter name to "_session_csrf_secret_token" and fix up tests to use new names
r7711 def session_csrf_secret_token(self):
Mads Kiilerich
tests: provide _authentication_token when POSTing...
r4993 """Return the CSRF protection token for the session - just like it
Søren Løvborg
auth: miscellaneous improvements and typo fixes
r5316 could have been screen scraped from a page with a form.
Mads Kiilerich
tests: provide _authentication_token when POSTing...
r4993 Only intended for testing but might also be useful for other kinds
of automation.
"""
Mads Kiilerich
helpers: rename internal names of authentication_token to clarify that secure_form is about session CSRF secrets - not authentication
r7709 return h.session_csrf_secret_token()